fixing non-null String must be provided to a Text widget - arrays

I'm quite new in flutter.
I am working on a quiz app and try to make every quiz has five questions
I faced some problems :
1- I don't want to repeat the same question in the same quiz.[my quiz also start with question number one every time].
2- Every time it reaches my question number ten [which in array] nine my app crash.
NOTE: I'm using a JSON file to store my questions.
int j = 1;
int i = 1;
var random_array;
genrandomarray() {
var distinctIds = [];
var rand = new Random();
for (int i = 1;;) {
distinctIds.add(rand.nextInt(10));
random_array = distinctIds.toSet().toList();
if (random_array.length < 10) {
continue;
} else {
break;
}
}
print(random_array);
}
setState(() {
if (j < 5) {
i = random_array[j];
j++;
} else {
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => resultpage(marks: marks),
));
}
disableAnswer = false;
});

genrandomarray() {
var rand = new Random();
make it choose random between questions
var distinctIds = [i = rand.nextInt(10) + 1];
for (int i = 0;;) {
to not crash when it reach to 10 question
distinctIds.add(rand.nextInt(10) + 1);
random_array = distinctIds.toSet().toList();
if (random_array.length < 10) {
continue;
} else {
break;
}
}
print(random_array);
}

Related

Generate Random Number Using math.random, But Without Repeats

For a yearly Christmas event for an organization I'm a part of, we usually hold a raffle where people have the opportunity to win free prizes by just attending and getting a number ticket at the door. We use a program written in Flash (Using ActionScript 2.0) that selects a random number utilizing math.random, with some parameters attached to it, as shown below:
//maxNr = 999999999999999;
initRandom = function(){
var nr = Math.ceil(Math.ceil(Math.random()*(maxNr));
var nrString = "";
for( var j=0; j<(maxNr.toString().length-nr.toString().length); j++){
nrString += "0";
}
nrString += nr.toString();
var holder = this.createEmptyMovieClip("holder",1);
for( i=0; i<maxNr.toString().length; i++ ){
var mc = holder.attachMovie("number","n"+i,i+10);
mc._x = i*350;
mc.anim_mc.gotoAndPlay( Math.floor(Math.random()*9) + 1 );
this["iv"+i] = setInterval( this, "revealNumber", 2000 + (500*i), nrString.substr(i,1), i );
}
// scale (if needed) and center
if( holder._width > Stage.width ){
holder._width = Stage.width;
holder._yscale = holder._xscale;
}
holder._x = Stage.width/2 - holder._width/2;
holder._y = 100;
// buttons
back_btn.onRelease = function(){
for(item in holder){
holder[item].removeMovieClip();
}
gotoAndStop("intro");
}
}
revealNumber = function( digit, i ){
clearInterval( this["iv"+i] );
holder["n"+i].gotoAndStop("done");
holder["n"+i]["number_txt"].text = digit;
}
initRandom();
stop();
It's meant to return a random number between 1 and 1000, as defined by:
go_btn.onRelease = function(){
maxNr = Math.max( 1000 , 1 );
gotoAndStop("random");
}
stop();
It was written by a member of our organization who unfortunately passed away during the year, and I have little to no programming knowledge but I am a quick learner and have actually modified some of the code to get to the point it is currently. However, I'm trying to add in a parameter that would disallow the function from repeating a number, ie, excluding an already generated number from being reselected.
I've spent days scouring any resource possible and have only met dead ends.
With the approach currently taken, is it possible to add in this parameter to this existing code, and how can I go about doing that?
Any help, suggestion or reply would be very greatly appreciated!
package
{
public class RandomGenerator
{
private var _st:Number;
private var _en:Number;
private var _len:Number;
private var _pos:Number;
private var _numPos:Number;
private var _myNums:Array;
private var _randNums:Array;
public function RandomGenerator(en:Number, st:Number = 0)
{
_st = st;
_en = en;
// just in case if params order mixup:
if(en < st){
_st = en;
_en = st;
}
_len = _en - _st + 1;
shuffle();
}
public function getNum():Number
{
// if passed last item:
if(_numPos == _len)shuffle();
var myResult:Number = _randNums[_numPos];
_numPos++;
return myResult;
}
private function shuffle():void
{
_numPos = 0;
_randNums = [];
_myNums = [];
// Creating Numbers Array:
var i:Number;
for(i = 0; i<_len; i++){ _myNums[i] = _st + i; }
// Creating shuffled Numbers Array:
i = 0;
while(_myNums.length > 0){
_pos = Math.round(Math.random()*(_myNums.length-1));
_randNums[i] = _myNums[_pos];
i++;
_myNums.splice(_pos,1);
}
}
public function get len():Number
{
return _len;
}
}
}
make an object from this class for example cardGenerator:RandomGenerator = new RandomGenerator(51, 0) and finally you can get random number without repeat with this codes:
for (var i:int = 0; i < cardGenerator.len; i++) {
trace(cardGenerator.getNum());
}
My AS2 is a bit rusty, but I think the following script explains the general idea. You need some registry to record generated numbers so you can skip them next time you generate one. I used the _global object so that this logic transcends even multiple instances of the following script.
// Create an Array to record generated numbers.
// The _global object is always present and can be accessed from anywhere.
if (_global.uniqueNr == undefined)
{
_global.uniqueNr = [];
}
function initRandom()
{
var nr;
do
{
nr = Math.ceil(Math.ceil(Math.random()*(maxNr));
}
while (_global.uniqueNr[nr] == true);
// Record the newly generated number so it would never drop again.
_global.uniqueNr[nr] = true;
// At this point you can be sure that "nr" contains a unique value.

My for loop won't display my object, but no errors show up

For some reason my for loop isn't working, the enemies won't spawn and nothing appears in the Output when I used trace. However, there also is no error, so I'm wondering what the issue is.
Here is my code:
var playerX = 0;
var playerY = 0;
var mapWidth = 5000;
var mapHeight = 5000;
//enemy
var myEnemies:Array = new Array();
var enemySprite:Sprite;
var Enemy:enemy;
var enemyCount:int = 0;
//event listeners
stage.addEventListener(Event.ENTER_FRAME, spawnEnemies);
//spawn enemies
function spawnEnemies(spawn:Event) {
if (enemyCount < 20) {
for (var i = 0; i < myEnemies.length; i++) {
enemySprite = new Sprite();
this.addChild(enemySprite);
Enemy = new enemy();
Enemy.x = (Math.random() * this.width);
Enemy.y = (Math.random() * this.height);
enemySprite.addChild(Enemy);
enemyCount++;
myEnemies[enemyCount] = enemySprite;
trace(myEnemies.length);
}
stage.addEventListener(Event.ENTER_FRAME, moveEnemy);
}
}
//move the enemies
function moveEnemy(enemyMovement:Event){
for (var k = 0; k < myEnemies.length; k++) {
trace("move enemy");
if (myEnemies[k].y > playerY) {
myEnemies[k].y -= 1;
myEnemies[k].rotation = 0;
}
else if (myEnemies[k].x < playerX) {
myEnemies[k].x += 1;
myEnemies[k].rotation = 90;
}
else if (myEnemies[k].y < playerY) {
myEnemies[k].y += 1;
myEnemies[k].rotation = 180;
}
else {
myEnemies[k].x -= 1;
myEnemies[k].rotation = 270;
}
}
}
Thank you for your help!
OK, I did not work with AS3 for a long time, but... Why do you expect new enemies to be created if myEnemies length is 0?
Also, you created two different ENTER_FRAME functions and there is no need to do that. Create only one function and call it for exmaple update:
private function update(e:event)
{
}
stage.addEventListener(Event.ENTER_FRAME, update);
You should not create new sprites using for loop inside ENTER_FRAME function, because this function runs 30 or more times in a second.
Create for loop inside "init" or "create" function, unless you want to update code on each frame.
Add 10 enemies:
for (var i = 0; i < 10; i++) {
Enemy = new enemy();
Enemy.x = (Math.random() * this.width);
Enemy.y = (Math.random() * this.height);
this.addChild(Enemy);
// add it to array
myEnemies.push(Enemy);
}
You cannot use myEnemies to create new Enemy sprite because it's empty, so you create 0 enemies. If you want to create 10 enemies use this code, or simple change number 10 to any number you want.

Cant access all children of element?

So i am adding some elements to a map control like this
foreach (var res in results)
{
if (res.geometry.location != null)
{
var pushpin = new Image();
pushpin.Name = "a";
BasicGeoposition bs = new BasicGeoposition { Latitude = res.geometry.location.lat, Longitude = res.geometry.location.lng };
pushpin.Source = new BitmapImage(uri);
pushpin.Height = 50;
pushpin.Width = 50;
myMap.Children.Add(pushpin);
MapControl.SetLocation(pushpin, new Geopoint(bs));
}
}
Now i want to remove elements names "a" form the control and i am using following code
int c = myMap.Children.Count;
for (int i = 0; i < c; i++)
{
if(myMap.Children.ElementAt(i) is Image)
{
var z = myMap.Children.ElementAt(i) as Image;
if(z.Name.Equals("a"))
{
myMap.Children.Remove(myMap.Children.ElementAt(i));
}
}
}
But always some elements are not getting removed ,for example the count of children is coming 21,but the loop is looping only 10 time.
How can i solve this problem?
try it with looping backwards so you dont mess up your collection during the loop.
int c = myMap.Children.Count - 1;
for (int i = c; i >= 0; i--)
{
if (myMap.Children.ElementAt(i) is Image)
{
var z = myMap.Children.ElementAt(i) as Image;
if(z.Name.Equals("a"))
{
myMap.Children.Remove(myMap.Children.ElementAt(i));
}
}
}

My if-statement doesn't work

It's either going to be "Riktig, bokstaven forekommer" for right letter chosen or otherwise. What have i done wrong, when i start it now none of the Messages show.
btnStart.addEventListener(MouseEvent.CLICK, start);
var feil:Array = new Array ;
var riktig:Array = new Array ;
var bokstav:Array = new Array ;
bokstav[0] = "b";
bokstav[1] = "r";
bokstav[2] = "e";
bokstav[3] = "v"
var txtBokstav:TextField = new TextField( );
txtBokstav.maxChars = 1;
txtBokstav.restrict = "a-z æ ø å";
txtBokstav.type = flash.text.TextFieldType.INPUT;
addChild(txtBokstav);
function start(evt)
{
var bokstavInn:String = String(txtBokstav.text);
if (txtBokstav.text.length == 1)
{
if (bokstav.indexOf(bokstavInn) >= 0)
{
txtUtskrift.text = "Riktig, bokstaven forekommer";
riktig.push(bokstavInn);
for (var i = 0; i < riktig.length; i++)
{
txtUtskrift.appendText(riktig[i] + ", ");
}
}
else
{
txtUtskrift.text = "Feil, bokstaven forekommer ikke";
feil.push(bokstavInn);
for (var l = 0; l < feil.length; l++)
{
txtUtskrift.appendText(feil[l] + ", ");
}
}
}
}
1) Are you sure that txtUtskrift is on the Stage and visible?
2) Make sure that start() is being called (use a breakpoint or trace)
3) As askmozo suggests, place trace statements in the possible flow of execution. So, at the beginning of the start function, and within each possible if condition. You might add an else for the text.length test:
function start( evt )
{
trace( "start()..." );
if (txtBokstav.text.length == 1)
{
// ... what you already have
}
else
{
trace( "txtBokstav length not valid:", txtBokStav.text.length );
}
trace( "...start()" );
}

AS3 - Remove spaces from an array for word game

I'm building a word search game using the following AS3 code. My problem is I need to have spaces in my array of words, so that I can have things like states names, but I need the spaces removed before the words go into the puzzle.
The other concern is also that when a person selects a word from the puzzle will it still match the word in the list even though the word in the list still has a space.
I've struggled with this for a few days now and could use some help.
I've pasted all appropriate code below, I believe. Thanks.
Rich
// words and grid
private var wordList:Array;
private var usedWords:Array;
private var grid:Array;
// sprites
private var letterSprites:Sprite;
private var wordsSprite:Sprite;
wordList = ("New York,New Jersey,South Carolina,North Carolina").split(",");
// set up the sprites
gameSprite = new Sprite();
addChild(gameSprite);
letterSprites = new Sprite();
gameSprite.addChild(letterSprites);
wordsSprite = new Sprite();
gameSprite.addChild(wordsSprite);
// array of letters
var letters:Array = placeLetters();
// create word list fields and sprites
for(var i:int=0;i<usedWords.length;i++) {
var newWord:TextField = new TextField();
newWord.defaultTextFormat = letterFormatForList;
if(i < 20){ // first list
newWord.x = listXposition;
newWord.y = i*spacingForList+listYposition;
} else { // second list
newWord.x = listXposition + 130;
newWord.y = i*spacingForList+listYposition - (20 * 19);
}
newWord.width = 135;
newWord.height = spacingForList;
newWord.text = usedWords[i];
newWord.selectable = false;
wordsSprite.addChild(newWord);
}
// set game state
dragMode = "none";
numFound = 0;
}
// place the words in a grid of letters
public function placeLetters():Array {
// create empty grid
var letters:Array = new Array();
for(var x:int=0;x<puzzleSize;x++) {
letters[x] = new Array();
for(var y:int=0;y<puzzleSize;y++) {
letters[x][y] = "*";
}
}
// make copy of word list
var wordListCopy:Array = wordList.concat();
usedWords = new Array();
// make 1000 attempts to add words
var repeatTimes:int = 1000;
repeatLoop:while (wordListCopy.length > wordsLeft) {
if (repeatTimes-- <= 0) break;
// pick a random word, location and direction
var wordNum:int = Math.floor(Math.random()*wordListCopy.length);
var word:String = wordListCopy[wordNum].toUpperCase();
x = Math.floor(Math.random()*puzzleSize);
y = Math.floor(Math.random()*puzzleSize);
var dx:int = Math.floor(Math.random()*3)-1;
var dy:int = Math.floor(Math.random()*3)-1;
if ((dx == 0) && (dy == 0)) continue repeatLoop;
// check each spot in grid to see if word fits
letterLoop:for (var j:int=0;j<word.length;j++) {
if ((x+dx*j < 0) || (y+dy*j < 0) || (x+dx*j >= puzzleSize) || (y+dy*j >= puzzleSize)) continue repeatLoop;
var thisLetter:String = letters[x+dx*j][y+dy*j];
if ((thisLetter != "*") && (thisLetter != word.charAt(j))) continue repeatLoop;
}
// insert word into grid
insertLoop:for (j=0;j<word.length;j++) {
letters[x+dx*j][y+dy*j] = word.charAt(j);
}
// remove word from list
wordListCopy.splice(wordNum,1);
usedWords.push(word);
}
// fill rest of grid with random letters
for(x=0;x<puzzleSize;x++) {
for(y=0;y<puzzleSize;y++) {
if (letters[x][y] == "*") {
letters[x][y] = String.fromCharCode(65+Math.floor(Math.random()*26));
}
}
}
return letters;
}
// player clicks down on a letter to start
public function clickLetter(event:MouseEvent) {
var letter:String = event.currentTarget.getChildAt(0).text;
startPoint = findGridPoint(event.currentTarget);
dragMode = "drag";
}
// player dragging over letters
public function overLetter(event:MouseEvent) {
if (dragMode == "drag") {
endPoint = findGridPoint(event.currentTarget);
// if valid range, show outline
outlineSprite.graphics.clear();
if (isValidRange(startPoint,endPoint)) {
drawOutline(outlineSprite,startPoint,endPoint,0xCCCCCC);
}
}
}
// mouse released
public function mouseRelease(event:MouseEvent) {
if (dragMode == "drag") {
dragMode = "none";
outlineSprite.graphics.clear();
// get word and check it
if (isValidRange(startPoint,endPoint)) {
var word = getSelectedWord();
checkWord(word);
}
}
}
// when a letter is clicked, find and return the x and y location
public function findGridPoint(letterSprite:Object):Point {
// loop through all sprites and find this one
for(var x:int=0;x<puzzleSize;x++) {
for(var y:int=0;y<puzzleSize;y++) {
if (grid[x][y] == letterSprite) {
return new Point(x,y);
}
}
}
return null;
}
// determine if range is in the same row, column, or a 45 degree diagonal
public function isValidRange(p1,p2:Point):Boolean {
if (p1.x == p2.x) return true;
if (p1.y == p2.y) return true;
if (Math.abs(p2.x-p1.x) == Math.abs(p2.y-p1.y)) return true;
return false;
}
// draw a thick line from one location to another
public function drawOutline(s:Sprite,p1,p2:Point,c:Number) {
var off:Point = new Point(offset.x+spacing/2, offset.y+spacing/2);
s.graphics.lineStyle(outlineSize,c);
s.graphics.moveTo(p1.x*spacing+off.x ,p1.y*spacing+off.y-3);
s.graphics.lineTo(p2.x*spacing+off.x ,p2.y*spacing+off.y-3);
}
// find selected letters based on start and end points
public function getSelectedWord():String {
// determine dx and dy of selection, and word length
var dx = endPoint.x-startPoint.x;
var dy = endPoint.y-startPoint.y;
var wordLength:Number = Math.max(Math.abs(dx),Math.abs(dy))+1;
// get each character of selection
var word:String = "";
for(var i:int=0;i<wordLength;i++) {
var x = startPoint.x;
if (dx < 0) x -= i;
if (dx > 0) x += i;
var y = startPoint.y;
if (dy < 0) y -= i;
if (dy > 0) y += i;
word += grid[x][y].getChildAt(0).text;
}
return word;
}
// check word against word list
public function checkWord(word:String) {
// loop through words
for(var i:int=0;i<usedWords.length;i++) {
// compare word
if (word == usedWords[i].toUpperCase()) {
foundWord(word);
}
// compare word reversed
var reverseWord:String = word.split("").reverse().join("");
if (reverseWord == usedWords[i].toUpperCase()) {
foundWord(reverseWord);
}
}
}
// word found, remove from list, make outline permanent
public function foundWord(word:String) {
sndSuccess=new success_sound();
sndSuccessChannel=sndSuccess.play(200);
so.data.totalWordsFound = so.data.totalWordsFound + 1;
so.flush();
// draw outline in permanent sprite
drawOutline(oldOutlineSprite,startPoint,endPoint,0xDDDDDD);
// find text field and set it to gray
for(var i:int=0;i<wordsSprite.numChildren;i++) {
if (TextField(wordsSprite.getChildAt(i)).text.toUpperCase() == word) {
TextField(wordsSprite.getChildAt(i)).textColor = 0x777777;
}
}
// see if all have been found
numFound++;
if (numFound == usedWords.length) {
if (so.data.difficulty == "Easy") {
so.data.easyWon = so.data.easyWon + 1;
}
if (so.data.difficulty == "Medium") {
so.data.mediumWon = so.data.mediumWon + 1;
}
if (so.data.difficulty == "Hard") {
so.data.hardWon = so.data.hardWon + 1;
}
so.flush();
endGame();
}
}
I'm hesitant to post an answer as I'm not really sure what's going on, but hopefully this info will help:
Keep your words in the arrays with spaces, that's a good idea. When you want to check against the words in your game, just convert both words to the same format using a function. eg:
var wordList:Array = ("New York,New Jersey,South Carolina,North Carolina").split(",");
var selectedWord:String = "NEWYORK";
// minWord converts all words to the same format of no spaces and all lower case.
function minWord(word:String):String {
return word.replace(/\s/g, "").toLowerCase();
}
// this loop checks all the words from your array against the selectedWord.
for each(var word:String in wordList) {
trace(minWord(word) + " == " + minWord(selectedWord) + "; ", minWord(word) == minWord(selectedWord));
}
Hope that helps!

Resources