问题描述
我目前正在尝试使用led创建记忆游戏,但是这变得很丢脸。从想法开始会更合乎逻辑。这个想法是在两个二极管的帮助下,播放了一些序列,您必须使用操纵杆重复该过程。我的程序应该看起来像这样...
void main() {
generateNewGame();
blinkLeds();
for (uint8_t index = 0; i < Game_Length; index++) {
if(waitForPress() != GameArray[index])
blinkFail();
return;
}
}
blinkSuccess();
}
这两个功能正常工作。
generateNewGame();
blinkLeds();
我对此功能有疑问
waitForPress()
我的“ GameArray”充满了1和0。 我要这样做,以便如果我将操纵杆转到左侧,那么函数“ waitForPress()”将返回1,并且在主菜单中,我要将其与我的“ GameArray”进行比较,如果为真,请检查下一个元素。与“游戏”数组的比较对我不起作用。另外,由于某种原因,我的左LED指示灯一直亮着,操纵杆没有响应。我希望我的话是有道理的,如果您有任何疑问,我准备补充这个问题。 此刻我的代码
#define F_cpu 2000000UL
#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
// Global
uint8_t Game[8];
int i;
const uint16_t n = 500;
void delay(uint16_t n) {
for(uint16_t i = 0; i < n ; i++) {
for(uint16_t j = 0; j < 200 ; j++) {
asm volatile ("nop");
}
}
}
// Function for filling the game array with ones and zeros
void RandomNumber() {
srand((unsigned int)time(NULL));
for(unsigned int i = 0; i < sizeof(Game)/sizeof(Game[0]); i++) {
int v = rand() % 2;
Game[i] = v;
}
}
// Function for flashing the Game array sequence
void PlayDemo() {
int i;
for(i = 0; i <= 8; i++) {
if(Game[i] == 1) {
PORTA = 0x80;
delay(n);
PORTA = 0x00;
delay(n);
}
else if (Game[i] == 0) {
PORTA = 0x01;
delay(n);
PORTA = 0x00;
delay(n);
}
else {
PORTA = 0x00;
}
}
}
int waitForPress() {
uint8_t x = PINF;
// Until the button is off,do nothing
while(!(x & 0x20) && !(x & 0x08)) {
x = PINF;
}
// Check if we press to the left
if(x & 0x20) {
// Last LED ON
PORTA = 0x80;
// Wait ( Debouncing )
delay(n);
return 1;
}
// Check if we press to the right side
if(x & 0x08) {
// First LED ON
PORTA = 0x01;
// Wait ( Debouncing )
delay(n);
return 0;
}
return 0;
}
int main(void) {
MCUCR |= 0x80;
MCUCR |= 0x80;
DDRA = 0xFF;
PORTF = 0x20;
RandomNumber();
PlayDemo();
while(1)
{
// Check all elements of the "Game" array
for(uint8_t index = 0; index < 8; index++) {
// If the output of the function "waitForPress()" is not equal to "Game" array element
if(waitForPress() != Game[index]) {
// End the game
break;
} else if(waitForPress() == Game[index]) {
// Turn all led ON
PORTA = 0xFF;
// Wait
delay(n);
// Turn all led OFF
PORTA = 0x00;
// Wait
delay(n);
}
}
}
}
解决方法
您的程序可能存在多个问题:
(1)首先:在将用户输入与游戏数组进行比较的FOR循环中,当用户输入正确答案时,您两次调用waitForPress()
。这不是您想要的,您的代码应如下所示:
//...
if (waitForPress() != Game[index])
{
//...
break;
}
else
{
//... (correct answer)
}
//...
或者您可以这样做:
//...
int userInput = waitForPress();
if (userInput != Game[index])
{
//...
break;
}
else
{
//... (correct answer)
}
//...
(2)假设(1)中的代码已更正,我认为另一个主要问题是您通常处理用户输入的方式。让我来说明问题:
- 开始时,没有任何操作。您的主程序名为
waitForPress()
,并“塞住”了WHILE循环,等待用户按下操纵杆。 li> - 当用户最终按下操纵杆时,该函数返回1或0。
- 在您的主程序中,此返回值是根据FOR循环中的IF语句处理的(请参阅(1))。
- 此后不久,
waitForPress()
再次被调用(在输入错误的情况下,几乎立即;在延迟后输入的情况是正确的;我假设这意味着像简短的输入一样)所有LED的“闪烁”可能持续几百毫秒。 - 由于仍然按下该按钮(人类很慢!),
waitForPress()
立即返回。现在,您的程序以为您再次输入了相同的内容,尽管您甚至没有根据自己的理解进行第二次输入。
要解决此问题,您需要检测信号沿。最简单的方法是在等待一个按钮按下之前,确保释放操纵杆。您可以像这样修改waitForPress()
:
int waitForPress() {
uint8_t x = PINF;
// Make sure that the user released the joystick
while((x & 0x20) || (x & 0x08)) {
x = PINF;
}
// Until one button comes on,do nothing
while(!(x & 0x20) && !(x & 0x08)) {
x = PINF;
}
//...
此外,您可能希望添加处理弹跳的机制。
(3)您永远不会在main()
函数中退出WHILE循环。因此,您的程序始终保持在期望用户输入的状态。
(4)在函数PlayDemo()
中,您正在访问“不存在的”游戏数组元素(Game[8]
),因为FOR循环的条件是i <= 8
并且不是i < 8
。
此外,可能存在硬件或硬件配置问题。可能很难在StackOverflow上找到这些问题,因为我没有或不知道您的确切设置。您可以运行测试程序来检查硬件是否运行正常。