【问题标题】:Shuffle NSDictionary随机播放 NSDictionary
【发布时间】:2013-11-10 11:58:58
【问题描述】:

我正在尝试制作一个测验应用程序,我希望用户单击一个按钮,程序会显示一个随机问题。我尝试使用 arc4random,但它确实重复了这些问题,我想要一个真正随机的方法。所以在这个论坛上有人告诉我使用洗牌方法。我试过了:

-(IBAction)NextQuestion:(id)sender{

NSDictionary * questions = [[NSDictionary alloc] initWithObjectsAndKeys:
                          @"questionone", Question.text = [NSString stringWithFormat:@"xxxxxxxxxxxxxxxx?"],
                           Right2.hidden = NO,
                           Wrong3.hidden = NO,
                           Wrong1.hidden = NO,
                           Answer1.text = [NSString stringWithFormat:@"xxxx"],
                           Answer2.text = [NSString stringWithFormat:@"xxxx"],
                           Answer3.text = [NSString stringWithFormat:@"xxxx"],
                           @"questiontwo", Question.text = [NSString stringWithFormat:@"xxxxxxxxxxxxxxxxxxxx?"],
                           Right1.hidden = NO,
                           Wrong2hidden = NO,
                           Wrong3.hidden = NO,
                           Answer1.text = [NSString stringWithFormat:@"xxxx"],
                           Answer2.text = [NSString stringWithFormat:@"xxxx"],
                           Answer3.text = [NSString stringWithFormat:@"xxxx"],
                            nil];

NSMutableArray *question;
question = [NSMutableArray arrayWithObject:questions];



// shuffle
for (int i = (int)[question count] - 1; i > 0; --i) {
    [question exchangeObjectAtIndex: i
                  withObjectAtIndex: arc4random_uniform((uint32_t)i + 1)];
}

问题是,无论我提出多少问题,只有一个节目(通常是最后一个),所以我做错了什么?有人可以帮我吗?谢谢!!

【问题讨论】:

  • 何不做一个专门的类Question,然后对这个类的对象进行操作。使用NSMutableArray 而不是NSDictionary。对数组进行洗牌或排序很容易。 NS(Mutable)Dictionary 不能被打乱或排序,因为它不是有序的数据结构。
  • True Random Xcode 的可能重复项
  • 嘿 zaph 不是重复的,我从那个帖子中学到了,你给了我一个有用的答案,但你没有很好地解释它,否则你会有正确的答案,我不需要创建一个新问题。

标签: ios random nsdictionary shuffle


【解决方案1】:

如果键只是一个索引,请不要使用NSDictionary。默认情况下,它们排序!

// create a Question class with the properties number,text, answer1, ... etc. (need .h/.m and import it)

unsigned int maxCountOfQuestions = ...
NSMutableArray *tempArray = [NSMutableArray alloc] initWithCapacity: maxCountOfQuestions];
for (unsigned int index=0; index < maxCountOfQuestions; i++) {
    // make an designated initializer for your `Question` object
    Question *question = [[Question alloc] initWithText:@"textone" number:2 ...];
    [tempArray addObject:question];
}
NSArray *questions = [NSArray arrayFromArray:tempArray];
[questions shuffle]; // don't forget to import the category for the shuffle method

你想要一个NSArray,可以用这个分类来洗牌:

//  NSMutableArray_Shuffling.h

#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#else
#include <Cocoa/Cocoa.h>
#endif

// This category enhances NSMutableArray by providing
// methods to randomly shuffle the elements.
@interface NSMutableArray (Shuffling)
- (void)shuffle;
@end


//  NSMutableArray_Shuffling.m

#import "NSMutableArray_Shuffling.h"

@implementation NSMutableArray (Shuffling)

- (void)shuffle
{
    NSUInteger count = [self count];
    for (NSUInteger i = 0; i < count; ++i) {
        // Select a random element between i and end of array to swap with.
        NSInteger nElements = count - i;
        NSInteger n = (arc4random() % nElements) + i;
        [self exchangeObjectAtIndex:i withObjectAtIndex:n];
    }
}

@end

如果你想要一个来自 NSDictionary 的随机密钥,How do I select a random key from an NSDictionary? 上还有另一个很好的问题


示例

// main

unsigned int maxCountOfQuestions = 40u;
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithCapacity:maxCountOfQuestions];
Question *question1 = [[Question alloc] initWithTxt:@"Color of Apples?" Answer:@"yellow" Answer:@"green" Answer:@"blue" Number:1];
[tempArray addObject:question1];

Question *question2 = [[Question alloc] initWithTxt:@"Color of Bananas?" Answer:@"yellow" Answer:@"green" Answer:@"blue" Number:2];
[tempArray addObject:question2];

Question *question3 = [[Question alloc] initWithTxt:@"Color of Peaches?" Answer:@"yellow" Answer:@"green" Answer:@"blue" Number:3];
[tempArray addObject:question3];

Question *question4 = [[Question alloc] initWithTxt:@"Color of Oranges?" Answer:@"yellow" Answer:@"green" Answer:@"blue" Number:4];
[tempArray addObject:question4];

NSArray *questions = [NSArray arrayWithArray:tempArray];
[questions shuffle]; // don't forget to import the category for the shuffle method

// you can change the questions with changing only one property
questions[3].answer1 = @"purple";

// Questions.h
#import <Foundation/Foundation.h>

@interface Question : NSObject

@property (nonatomic, readwrite, strong) NSString *questionText;
@property (nonatomic, readwrite, strong) NSString *answer1;
@property (nonatomic, readwrite, strong) NSString *answer2;
@property (nonatomic, readwrite, strong) NSString *answer3;
@property (nonatomic, readwrite, unsafe_unretained) unsigned int number;

- (id)initWithTxt:(NSString *)txt Answer:(NSString *)a1 Answer:(NSString *)a2 Answer:(NSString *)a3 Number:(unsigned int)num;

@end

// Questions.m
#import "Question.h"

@implementation Question

@synthesize questionText = _questionText;
@synthesize answer1 = _answer1;
@synthesize answer2 = _answer2;
@synthesize answer3 = _answer3;
@synthesize number = _number;

//designated initializer
- (id)initWithTxt:(NSString *)txt Answer:(NSString *)a1 Answer:(NSString *)a2 Answer:(NSString *)a3 Number:(unsigned int)num
{
    self = [super init];
    if (self != nil) {
        _questionText = txt;
        _answer1 = a1;
        _answer2 = a2;
        _answer3 = a3;
        _number = num;
    }

    return self;
}

@end

【讨论】:

  • 感谢您的出色回答(而且很可能是正确的回答)。当您说“使用属性 number、text、answer1... 创建一个 Question 类”时,您的意思是我应该创建一个新类并将我所有的问题都放在那里?比如: Question.text = [NSString stringWithFormat:@"xxxxxxxxxxxxxxxx?"], Right2.hidden = NO, Wrong3.hidden = NO, Wrong1.hidden = NO, Answer1.text = [NSString stringWithFormat:@"xxxx"](. ..) 这一切?还有,房产编号是什么意思?谢谢!
  • @Mykod 添加了一个示例。如果问题不会改变,您可以使用静态NSArrays 发起问题。如果他们正在更改,最好实现 CoreData 数据库,其中 Question 是 NSManagedObject 的子类。
【解决方案2】:

你当然知道

question = [NSMutableArray arrayWithObject:questions];` 

导致只有一个对象的数组——questions 字典——所以“洗牌”数组是没有用的。

如果你想洗牌,做

NSMutableArray* keys = [[questions allKeys] mutableCopy];

并对其进行排序,然后从该数组中挑选元素以从字典中进行选择。

(但进一步观察,由于您执行 initObjectsAndKeys 的方式,您的字典中只会有一个问题,尽管它会出现两次,在两个不同的键下。)

【讨论】:

  • 那么你能解释一下我应该怎么做吗?我是 C 新手,从未使用过 NSMutableArrays 甚至 NSDictionaries,所以如果你足够大方,我需要更详细的解释。谢谢!
  • @Mykod - 首先,阅读documentation -- arrayWithObject 只将一个对象添加到数组中。但是你初始化字典的方式都是错误的,很难知道从哪里开始。叹息...我会用一些信息编辑我的答案。
  • 再想一想,你的初始化比我想象的还要糟糕。您要么需要定义一个Question 类,要么让每个问题成为一个内部字典,其中包含文本、正确、错误1、错误2、答案1 等键。
  • 我用我的问题和答案创建了一个 .plist,然后我添加了我的随机播放和显示方法,但它仍然重复了一些问题(有时)。我不知道我做错了什么。
  • @Mykod - 面对现实 - 你完全不知道自己在做什么。从更简单的事情开始,并确保您了解每一步都在做什么。虽然 Apple 的文档有点糟糕,但它仍然不是那么糟糕,所以在开始使用它们进行编码之前,请先研究类(例如 NSArray 和 NSDictionary)的文档。
猜你喜欢
  • 2023-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-02
  • 1970-01-01
  • 2016-12-29
  • 2015-11-16
相关资源
最近更新 更多