As the video above shows, there is still a way to do both. One at a time, I am sifting the characters in my sting of digits one place to the left. Currently I have set it up to do that at the rate of one per second. Later when we start to build skill levels into the game we will have a way to speed that up to make the puzzle more challenging.
Just for demonstration purposes, the video and the code that we will discuss here, repeats the randomization of the digits and walks through the shifting process. Once the user presses the button to start the game, the button is no longer read by the program so it does nothing but light the LED on the board. We will put it to work in part 4.
So let's look at what makes all this work. The key to digit shifting routine is the command
This line determines where the next character we print on the LCD is going to appear.
lcd.setCursor(tick + 2,0);
lcd.setCursor(x,y) requires two values. The first is which column: 0 - 15, and the second is which row: 0-1. With those two items you can print anywhere on the display. Think of it as a starting point. First you print a letter, or a word, here and the next time you print, your characters will be automatically appear in the next position. tick starts out at zero and we increment it each time we print a digit until every digit has been printed again in its new spot. We also use tick to determine which character in the string to print:
That gives us two copies of the same digit, so we simply follow up by printing a space which erases the unwanted image. We don't need to fuss over where, because we know that it will be the next character after the last one we printed. I have packaged all of this into the following function.
lcd.print(workingString[tick]);
The 'else' part of the function is just some temporary code to let us see how this is going to play on our display. To make this all work, we need to add the following highlight line to our loop() function.
void shiftLeft(){ if (tick < 10){ delay(1000); lcd.setCursor(tick + 2,0); lcd.print(workingString[tick]); lcd.print(' '); tick++; }else{ delay(1500); lcd.clear(); delay(1500); scrambleString(); displayWorkingString(); tick = 0; } }
That let's us test our procedures, we will move the line to a new location later.
void loop() { btnPress = digitalRead(myButton); if (btnPress==1){ digitalWrite(1,1); }else{ digitalWrite(1,0); } shiftLeft(); }
So what's next? We will need to check Sparky's button while the numbers are shifting left. Stop that nonsense in its tracks and flip a batch of digits around. Then we do it all again. As before, you can copy the code we've written so far below and try it yourself. C U next time.
/* ATtiny85 as an I2C Master Ex2 BroHogan 1/21/11
* Modified for Digistump - Digispark LCD Shield by Erik Kettenburg 11/2012
* SETUP:
* ATtiny Pin 1 = (RESET) N/U ATtiny Pin 2 = (D3) N/U
* ATtiny Pin 3 = (D4) to LED1 ATtiny Pin 4 = GND
* ATtiny Pin 5 = SDA on DS1621 & GPIO ATtiny Pin 6 = (D1) to LED2
* ATtiny Pin 7 = SCK on DS1621 & GPIO ATtiny Pin 8 = VCC (2.7-5.5V)
* NOTE! - It's very important to use pullups on the SDA & SCL lines!
* PCA8574A GPIO was used wired per instructions in "info" folder in the LiquidCrystal_I2C lib.
* This ex assumes A0-A2 are set HIGH for an addeess of 0x3F
* LiquidCrystal_I2C lib was modified for ATtiny - on Playground with TinyWireM lib.
* TinyWireM USAGE & CREDITS: - see TinyWireM.h
*/
//#define DEBUG
#include <TinyWireM.h> // I2C Master lib for ATTinys which use USI - comment this out to use with standard arduinos
#include <LiquidCrystal_I2C.h> // for LCD w/ GPIO MODIFIED for the ATtiny85
#define GPIO_ADDR 0x27 // (PCA8574A A0-A2 @5V) typ. A0-A3 Gnd 0x20 / 0x38 for A - 0x27 is the address of the Digispark LCD modules.
LiquidCrystal_I2C lcd(GPIO_ADDR,16,2); // set address & 16 chars / 2 lines
String winner ="0123456789"; // a test string to easily see game is over
String workingString = "0123456789"; // all the digits that we will scramble at the beginning of the game
int rnd; // will hold a random number for us.
int myButton = 5; // our button hooks up here
int btnPress; // is it down or not
byte tick = 0;
void setup(){
TinyWireM.begin(); // initialize I2C lib - comment this out to use with standard arduinos
lcd.init(); // initialize the lcd
lcd.clear();
lcd.backlight();
pinMode (myButton, INPUT);
pinMode(1, OUTPUT); //LED on Model A
scramblePrompt();
scrambleString();
displayWorkingString();
delay(3000);
}
void loop() {
btnPress = digitalRead(myButton);
if (btnPress==1){
digitalWrite(1,1);
}else{
digitalWrite(1,0);
}
shiftLeft();
}
void shiftLeft(){
if (tick < 10){
delay(1000);
lcd.setCursor(tick + 2,0);
lcd.print(workingString[tick]);
lcd.print(' ');
tick++;
}else{
delay(1500);
lcd.clear();
delay(1500);
scrambleString();
displayWorkingString();
tick = 0;
}
}
void scramblePrompt(){
lcd.noCursor();
lcd.print("NUMBER FLIP-FLOP");
lcd.setCursor(0,1);
lcd.print("Press Button Now");
do {
rnd=random(9);
} while (!digitalRead(myButton));
}
void scrambleString() {
lcd.clear();
lcd.print("NUMBER FLIP-FLOP");
for (int i=0; i<10; i++){
rnd=random(9);
swap(i,rnd);
}
delay(2000);
lcd.clear();
}
void swap(int x, int y){
byte hold=workingString[x];
workingString[x]=workingString[y];
workingString[y]=hold;
}
void displayWorkingString(){
lcd.setCursor(3,0);
lcd.print(workingString);
lcd.noCursor();
}
No comments:
Post a Comment