这篇博客介绍了我是怎样通过自顶而下的方法一步步开发出一个字符版本的贪吃蛇游戏,并利用此前实现的智能蛇开发出全新的人机大战贪吃蛇。
首先我们先实现一条能根据输入移动的蛇。
这条蛇的伪代码如下:
输出字符矩阵
WHILE not 游戏结束 DO
ch=等待输入
CASE ch DO
‘A’:左前进一步,break
‘D’:右前进一步,break
‘W’:上前进一步,break
‘S’:下前进一步,break
END CASE
输出字符矩阵
END WHILE
输出 Game Over!!!
在实现时,首先管理好程序的头部:
#define SNAKE_MAX_LENGTH 20
#define SNAKE_HEAD 'H'
#define SNAKE_BODY 'X'
#define BLANK_CELL ' '
#define SNAKE_FOOD '$'
#define WALL_CELL '*'
#define MAP_SIZE 12
//snake stepping: dy = -1(up), 1(down); dx = -1(left), 1(right), 0(no move)
void snakeMove(int, int);
// put a food randimized on a blank cell
void put_money(void);
//output cells of the grid
void output(void);
//output gameover
void gameover(void);
char map[MAP_SIZE][MAP_SIZE] =
{
"************",
"*XXXXH *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"************",
};
// variables for snake and the initial values
int snakeX[SNAKE_MAX_LENGTH] = {1, 2, 3, 4, 5};
int snakeY[SNAKE_MAX_LENGTH] = {1, 1, 1, 1, 1};
int snakeLength = 5;
int isGameOver = 0;
然后按伪代码编写 main 函数:
int main(int argc, const char * argv[]) {
char c;
output();
while (isGameOver == 0) { // if game is not over
scanf("%c", &c); //
while (c == '\n') {
scanf("%c", &c);
}
switch(c){
case 'a':
snakeMove(-1, 0);
break;
case 'd':
snakeMove(1, 0);
break;
case 'w':
snakeMove(0, 1);
break;
case 's':
snakeMove(0, -1);
break;
default:
break;
}
output();
}
gameover();
return 0;
}
然后一个个实现 main 中的函数:
void snakeMove(int dx, int dy){
int i = snakeLength - 1;
// check if snake is going backward
if (snakeX[i] + dx == snakeX[i - 1] && snakeY[i] - dy == snakeY[i - 1]) {
return;
}
i = 0;
// turn TAIL into ' '
map[snakeY[i]][snakeX[i]] = ' ';
// make every BODY move forward
for (i = 0; i < snakeLength-1; i ++) {
snakeX[i] = snakeX[i+1];
snakeY[i] = snakeY[i+1];
}
// display every BODY
for (i = 1; i < snakeLength - 1; i ++) {
map[snakeY[i]][snakeX[i]] = SNAKE_BODY;
}
// make HEAD move
snakeX[i] += dx;
snakeY[i] -= dy;
// check if HEAD is moving to somewhere blank
if (map[snakeY[i]][snakeX[i]] != ' ') {
isGameOver = 1; // if not, game over
return;
}
// if so, display HEAD
map[snakeY[i]][snakeX[i]] = SNAKE_HEAD;
}
void output(void){
//system("clear && printf '\e[3J'");
//system("clear && '\e[3J'");
//system("\033[2J");
//system("\e[3J");
// if in windows environment, change the statement into:
// system("cls");
int i = 0, j = 0;
for (i = 0 ; i < MAP_SIZE; i ++) {
for (j = 0; j < MAP_SIZE; j ++) {
printf("%c",map[i][j]);
}
printf("\n");
}
}
void gameover(void){
printf("Game Over!");
}
接下来就要让这条蛇有吃东西的功能了。
首先需要实现一个在空白位置放食物的函数:
void put_money(void){
if (isFoodEaten) {
foodX = rand() % 10 + 1;
foodY = rand() % 10 + 1;
while (map[foodY][foodX] != ' ') {
foodX = rand() % 10 + 1;
foodY = rand() % 10 + 1;
}
map[foodY][foodX] = SNAKE_FOOD;
isFoodEaten = 0;
}
}
并修改 snakeMove 函数:
void snakeMove(int dx, int dy){
int i = snakeLength - 1;
// check if snake is going backward
if (snakeX[i] + dx == snakeX[i - 1] && snakeY[i] - dy == snakeY[i - 1]) {
return;
}
// check if snake is eating the food
if (map[snakeY[i] - dy][snakeX[i] + dx] == '$'){
map[snakeY[i] - dy][snakeX[i] + dx] = 'H';
map[snakeY[i]][snakeX[i]] = 'X';
snakeLength += 1;
// add HEAD position
snakeX[snakeLength-1] = snakeX[i] + dx;
snakeY[snakeLength-1] = snakeY[i] - dy;
isFoodEaten = 1;
return;
}
i = 0;
// turn TAIL into ' '
map[snakeY[i]][snakeX[i]] = ' ';
// make every BODY move forward
for (i = 0; i < snakeLength-1; i ++) {
snakeX[i] = snakeX[i+1];
snakeY[i] = snakeY[i+1];
}
// display every BODY
for (i = 1; i < snakeLength - 1; i ++) {
map[snakeY[i]][snakeX[i]] = SNAKE_BODY;
}
// make HEAD move
snakeX[i] += dx;
snakeY[i] -= dy;
// check if HEAD is moving to somewhere blank
if (map[snakeY[i]][snakeX[i]] != ' ') {
isGameOver = 1; // if not, game over
return;
}
// if so, display HEAD
map[snakeY[i]][snakeX[i]] = SNAKE_HEAD;
}
能吃的蛇距离可玩的贪吃蛇游戏还有一些距离。主要问题在于蛇不能每个一端时间自动前进;并且输入时还需要摁回车确认。
我参考了这篇文章:Linux下非阻塞地检测键盘输入的方法 (整理),在原来的基础上加入了 kbhit() 功能,解决上面的问题。
具体代码如下:
//
// main.c
// snake_play1
//
// Created by 尤大智 on 2017/12/24.
// Copyright © 2017年 尤大智. All rights reserved.
//
#include
#include
#include
#include
#include
#include
#include
#include
#define SNAKE_MAX_LENGTH 100
#define SNAKE_HEAD 'H'
#define SNAKE_BODY 'X'
#define BLANK_CELL ' '
#define SNAKE_FOOD '$'
#define WALL_CELL '*'
#define MAP_SIZE 20
static struct termios ori_attr, cur_attr;
static __inline
int tty_reset(void)
{
if (tcsetattr(STDIN_FILENO, TCSANOW, &ori_attr) != 0)
return -1;
return 0;
}
static __inline
int tty_set(void)
{
if ( tcgetattr(STDIN_FILENO, &ori_attr) )
return -1;
memcpy(&cur_attr, &ori_attr, sizeof(cur_attr) );
cur_attr.c_lflag &= ~ICANON;
// cur_attr.c_lflag |= ECHO;
cur_attr.c_lflag &= ~ECHO;
cur_attr.c_cc[VMIN] = 1;
cur_attr.c_cc[VTIME] = 0;
if (tcsetattr(STDIN_FILENO, TCSANOW, &cur_attr) != 0)
return -1;
return 0;
}
static __inline
int kbhit(void)
{
fd_set rfds;
struct timeval tv;
int retval;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 0;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
/* Don't rely on the value of tv now! */
if (retval == -1) {
perror("select()");
return 0;
} else if (retval)
return 1;
/* FD_ISSET(0, &rfds) will be true. */
else
return 0;
return 0;
}
//snake stepping: dy = -1(up), 1(down); dx = -1(left), 1(right), 0(no move)
void snakeMove(int, int);
// put a food randimized on a blank cell
void put_money(void);
//output cells of the grid
void output(void);
//output gameover
void gameover(void);
char map[MAP_SIZE][MAP_SIZE];
void start(void);
// variables for snake and the initial values
int snakeX[SNAKE_MAX_LENGTH] = {1, 2, 3, 4, 5};
int snakeY[SNAKE_MAX_LENGTH] = {1, 1, 1, 1, 1};
int snakeLength = 5;
// variables for food
int foodX;
int foodY;
int isGameOver = 0;
int isFoodEaten = 1;
int score = 0;
int main(int argc, const char * argv[]) {
while (1) {
start();
//设置终端进入非缓冲状态
int tty_set_flag;
tty_set_flag = tty_set();
char c = 'd';
srand((unsigned int)time(NULL));
put_money();
output();
while (isGameOver == 0) { // if game is not over
if(kbhit()){
c = getchar();
usleep(500000);
}
else{
usleep(500000);
}
switch(c){
case 'a':
snakeMove(-1, 0);
break;
case 'd':
snakeMove(1, 0);
break;
case 'w':
snakeMove(0, 1);
break;
case 's':
snakeMove(0, -1);
break;
default:
break;
}
put_money();
output();
}
gameover();
printf("press ANY button to restart or press Q to quit.\n");
c = getchar();
if (c == 'q') {
break;
}
//恢复终端设置
if(tty_set_flag == 0)
tty_reset();
}
return 0;
}
void snakeMove(int dx, int dy){
int i = snakeLength - 1;
// check if snake is going backward
if (snakeX[i] + dx == snakeX[i - 1] && snakeY[i] - dy == snakeY[i - 1]) {
return;
}
// check if snake is eating the food
if (map[snakeY[i] - dy][snakeX[i] + dx] == '$'){
map[snakeY[i] - dy][snakeX[i] + dx] = 'H';
map[snakeY[i]][snakeX[i]] = 'X';
snakeLength += 1;
// add HEAD position
snakeX[snakeLength-1] = snakeX[i] + dx;
snakeY[snakeLength-1] = snakeY[i] - dy;
isFoodEaten = 1;
score ++;
return;
}
i = 0;
// turn TAIL into ' '
map[snakeY[i]][snakeX[i]] = ' ';
// make every BODY move forward
for (i = 0; i < snakeLength-1; i ++) {
snakeX[i] = snakeX[i+1];
snakeY[i] = snakeY[i+1];
}
// display every BODY
for (i = 1; i < snakeLength - 1; i ++) {
map[snakeY[i]][snakeX[i]] = SNAKE_BODY;
}
// make HEAD move
snakeX[i] += dx;
snakeY[i] -= dy;
// check if HEAD is moving to somewhere blank
if (map[snakeY[i]][snakeX[i]] != ' ') {
isGameOver = 1; // if not, game over
return;
}
// if so, display HEAD
map[snakeY[i]][snakeX[i]] = SNAKE_HEAD;
}
void output(void){
//system("clear && \033[2J");
system("clear && printf '\e[3J'");
// if in windows environment, change the statement into:
// system("cls");
int i = 0, j = 0;
printf("score : %d\n", score);
for (i = 0 ; i < MAP_SIZE; i ++) {
for (j = 0; j < MAP_SIZE; j ++) {
printf("%c",map[i][j]);
}
printf("\n");
}
}
void gameover(void){
printf("Game Over!\nYour score is %d.\n", score);
}
void start(void){
snakeLength = 5;
score = 0;
int i = 0, j = 0;
for (i = 0; i < MAP_SIZE; i ++) {
for (j = 0; j < MAP_SIZE; j ++) {
map[i][j] = ' ';
}
}
for (i = 0; i < MAP_SIZE; i ++) {
map[0][i] = '*';
map[MAP_SIZE-1][i] = '*';
map[i][0] = '*';
map[i][MAP_SIZE-1] = '*';
}
for (i = 0; i <= 4; i ++) {
snakeX[i] = i+1;
snakeY[i] = 1;
map[snakeY[i]][snakeX[i]] = 'X';
}
map[snakeY[snakeLength-1]][snakeX[snakeLength-1]] = 'H';
isGameOver = 0;
isFoodEaten = 1;
}
void put_money(void){
if (isFoodEaten) {
foodX = rand() % 10 + 1;
foodY = rand() % 10 + 1;
while (map[foodY][foodX] != ' ') {
foodX = rand() % 10 + 1;
foodY = rand() % 10 + 1;
}
map[foodY][foodX] = SNAKE_FOOD;
isFoodEaten = 0;
}
}
于是一个如下图所示的字符版本贪吃蛇游戏就实现了:
利用此前实现的智能蛇程序,我想到可以把它加进游戏,使玩家和这只蛇对战一下,看看谁能活得更久,吃得更多。
具体代码如下:
//
// main.c
// snake_battle
//
// Created by 尤大智 on 2017/12/26.
// Copyright © 2017年 尤大智. All rights reserved.
//
#include
#include
#include
#include
#include
#include
#include
#include
#define SNAKE_MAX_LENGTH 100
#define SNAKE_HEAD 'H'
#define SNAKE_BODY 'X'
#define BLANK_CELL ' '
#define SNAKE_FOOD '$'
#define WALL_CELL '*'
#define MAP_SIZE 20
// variables for snake and the initial values
int snakePlayerX[SNAKE_MAX_LENGTH] = {1, 2, 3, 4, 5};
int snakePlayerY[SNAKE_MAX_LENGTH] = {1, 1, 1, 1, 1};
int snakeAIX[SNAKE_MAX_LENGTH] = {1, 2, 3, 4, 5};
int snakeAIY[SNAKE_MAX_LENGTH] = {1, 1, 1, 1, 1};
int snakePlayerLength = 5;
int snakeAILength = 5;
// variables for food
int foodX;
int foodY;
int isGameOverPlayer = 0;
int isGameOverAI = 0;
int isFoodEaten = 1;
int scorePlayer = 0;
int scoreAI = 0;
char mapPlayer[MAP_SIZE][MAP_SIZE];
char mapAI[MAP_SIZE][MAP_SIZE];
void start(void);
static struct termios ori_attr, cur_attr;
static __inline
int tty_reset(void)
{
if (tcsetattr(STDIN_FILENO, TCSANOW, &ori_attr) != 0)
return -1;
return 0;
}
static __inline
int tty_set(void)
{
if ( tcgetattr(STDIN_FILENO, &ori_attr) )
return -1;
memcpy(&cur_attr, &ori_attr, sizeof(cur_attr) );
cur_attr.c_lflag &= ~ICANON;
// cur_attr.c_lflag |= ECHO;
cur_attr.c_lflag &= ~ECHO;
cur_attr.c_cc[VMIN] = 1;
cur_attr.c_cc[VTIME] = 0;
if (tcsetattr(STDIN_FILENO, TCSANOW, &cur_attr) != 0)
return -1;
return 0;
}
static __inline
int kbhit(void)
{
fd_set rfds;
struct timeval tv;
int retval;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 0;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
/* Don't rely on the value of tv now! */
if (retval == -1) {
perror("select()");
return 0;
} else if (retval)
return 1;
/* FD_ISSET(0, &rfds) will be true. */
else
return 0;
return 0;
}
//snake stepping: dy = -1(up), 1(down); dx = -1(left), 1(right), 0(no move)
void snakePlayerMove(int, int);
void snakeAIMove(int, int);
// put a food randimized on a blank cell
void put_money(void);
//output cells of the grid
void output(void);
//determine AI where to go next
char whereGoNext(void);
//output gameover
void gameover(void);
int main(int argc, const char * argv[]) {
while (1) {
start();
//设置终端进入非缓冲状态
int tty_set_flag;
tty_set_flag = tty_set();
char cPlayer = 'd', cAI = 'd';
srand((unsigned int)time(NULL));
put_money();
output();
while (isGameOverPlayer == 0 && isGameOverAI == 0) { // if game is not over
if(kbhit()){
cPlayer = getchar();
usleep(500000);
}
else{
usleep(500000);
}
cAI = whereGoNext();
switch(cPlayer){
case 'a':
snakePlayerMove(-1, 0);
break;
case 'd':
snakePlayerMove(1, 0);
break;
case 'w':
snakePlayerMove(0, 1);
break;
case 's':
snakePlayerMove(0, -1);
break;
default:
break;
}
switch(cAI){
case 'a':
snakeAIMove(-1, 0);
break;
case 'd':
snakeAIMove(1, 0);
break;
case 'w':
snakeAIMove(0, 1);
break;
case 's':
snakeAIMove(0, -1);
break;
default:
break;
}
put_money();
output();
}
gameover();
usleep(1000000);
printf("press R to restart or press Q to quit.\n");
cPlayer = getchar();
while (cPlayer != 'r') {
if (cPlayer == 'q') {
return 0;
}
cPlayer = getchar();
}
//恢复终端设置
if(tty_set_flag == 0)
tty_reset();
}
return 0;
}
void snakePlayerMove(int dx, int dy){
int i = snakePlayerLength - 1;
// check if snake is going backward
if (snakePlayerX[i] + dx == snakePlayerX[i - 1] && snakePlayerY[i] - dy == snakePlayerY[i - 1]) {
return;
}
// check if snake is eating the food
if (mapPlayer[snakePlayerY[i] - dy][snakePlayerX[i] + dx] == '$'){
mapPlayer[snakePlayerY[i] - dy][snakePlayerX[i] + dx] = 'H';
mapPlayer[snakePlayerY[i]][snakePlayerX[i]] = 'X';
snakePlayerLength += 1;
// add HEAD position
snakePlayerX[snakePlayerLength-1] = snakePlayerX[i] + dx;
snakePlayerY[snakePlayerLength-1] = snakePlayerY[i] - dy;
isFoodEaten = 1;
scorePlayer ++;
return;
}
i = 0;
// turn TAIL into ' '
mapPlayer[snakePlayerY[i]][snakePlayerX[i]] = ' ';
// make every BODY move forward
for (i = 0; i < snakePlayerLength-1; i ++) {
snakePlayerX[i] = snakePlayerX[i+1];
snakePlayerY[i] = snakePlayerY[i+1];
}
// display every BODY
for (i = 1; i < snakePlayerLength - 1; i ++) {
mapPlayer[snakePlayerY[i]][snakePlayerX[i]] = SNAKE_BODY;
}
// make HEAD move
snakePlayerX[i] += dx;
snakePlayerY[i] -= dy;
// check if HEAD is moving to somewhere blank
if (mapPlayer[snakePlayerY[i]][snakePlayerX[i]] != ' ') {
isGameOverPlayer = 1; // if not, game over
return;
}
// if so, display HEAD
mapPlayer[snakePlayerY[i]][snakePlayerX[i]] = SNAKE_HEAD;
}
void snakeAIMove(int dx, int dy){
int i = snakeAILength - 1;
// check if snake is going backward
if (snakeAIX[i] + dx == snakeAIX[i - 1] && snakeAIY[i] - dy == snakeAIY[i - 1]) {
return;
}
// check if snake is eating the food
if (mapAI[snakeAIY[i] - dy][snakeAIX[i] + dx] == '$'){
mapAI[snakeAIY[i] - dy][snakeAIX[i] + dx] = 'H';
mapAI[snakeAIY[i]][snakeAIX[i]] = 'X';
snakeAILength += 1;
// add HEAD position
snakeAIX[snakeAILength-1] = snakeAIX[i] + dx;
snakeAIY[snakeAILength-1] = snakeAIY[i] - dy;
isFoodEaten = 1;
scoreAI ++;
return;
}
i = 0;
// turn TAIL into ' '
mapAI[snakeAIY[i]][snakeAIX[i]] = ' ';
// make every BODY move forward
for (i = 0; i < snakeAILength-1; i ++) {
snakeAIX[i] = snakeAIX[i+1];
snakeAIY[i] = snakeAIY[i+1];
}
// display every BODY
for (i = 1; i < snakeAILength - 1; i ++) {
mapAI[snakeAIY[i]][snakeAIX[i]] = SNAKE_BODY;
}
// make HEAD move
snakeAIX[i] += dx;
snakeAIY[i] -= dy;
// check if HEAD is moving to somewhere blank
if (mapAI[snakeAIY[i]][snakeAIX[i]] != ' ') {
isGameOverAI = 1; // if not, game over
return;
}
// if so, display HEAD
mapAI[snakeAIY[i]][snakeAIX[i]] = SNAKE_HEAD;
}
void start(void){
snakePlayerLength = 5;
snakeAILength = 5;
scorePlayer = 0;
scoreAI = 0;
int i = 0, j = 0;
for (i = 0; i < MAP_SIZE; i ++) {
for (j = 0; j < MAP_SIZE; j ++) {
mapPlayer[i][j] = BLANK_CELL;
mapAI[i][j] = BLANK_CELL;
}
}
for (i = 0; i < MAP_SIZE; i ++) {
mapPlayer[0][i] = WALL_CELL;
mapPlayer[MAP_SIZE-1][i] = WALL_CELL;
mapPlayer[i][0] = WALL_CELL;
mapPlayer[i][MAP_SIZE-1] = WALL_CELL;
mapAI[0][i] = WALL_CELL;
mapAI[MAP_SIZE-1][i] = WALL_CELL;
mapAI[i][0] = WALL_CELL;
mapAI[i][MAP_SIZE-1] = WALL_CELL;
}
for (i = 0; i <= 4; i ++) {
snakePlayerX[i] = i+1;
snakeAIX[i] = i+1;
snakePlayerY[i] = 1;
snakeAIY[i] = 1;
mapPlayer[snakePlayerY[i]][snakePlayerX[i]] = SNAKE_BODY;
mapAI[snakeAIY[i]][snakeAIX[i]] = SNAKE_BODY;
}
mapPlayer[snakePlayerY[snakePlayerLength-1]][snakePlayerX[snakePlayerLength-1]] = SNAKE_HEAD;
mapAI[snakeAIY[snakePlayerLength-1]][snakeAIX[snakePlayerLength-1]] = SNAKE_HEAD;
isGameOverPlayer = 0;
isGameOverAI = 0;
isFoodEaten = 1;
}
void put_money(void){
if (isFoodEaten) {
foodX = rand() % 10 + 1;
foodY = rand() % 10 + 1;
while (mapPlayer[foodY][foodX] != BLANK_CELL || mapAI[foodY][foodX] != BLANK_CELL) {
foodX = rand() % 10 + 1;
foodY = rand() % 10 + 1;
}
mapPlayer[foodY][foodX] = SNAKE_FOOD;
mapAI[foodY][foodX] = SNAKE_FOOD;
isFoodEaten = 0;
}
}
void output(void){
system("clear && printf '\e[3J'");
// if in windows environment, change the statement into:
// system("cls");
int i = 0, j = 0;
printf("score : %d\n", scorePlayer);
for (i = 0 ; i < MAP_SIZE; i ++) {
for (j = 0; j < MAP_SIZE; j ++) {
printf("%c",mapPlayer[i][j]);
}
printf("\n");
}
printf("\nscore : %d\n", scoreAI);
for (i = 0 ; i < MAP_SIZE; i ++) {
for (j = 0; j < MAP_SIZE; j ++) {
printf("%c",mapAI[i][j]);
}
printf("\n");
}
}
char whereGoNext(void){
char move[4] = {'a', 'd', 'w', 's'};
int minDistIndex = 0;
int distance[4] = {0, 0, 0, 0};
int i = snakeAILength - 1;
int dx = 0, dy = 0;
int moveIndex = 0;
for (moveIndex = 0; moveIndex < 4; moveIndex ++) {
switch (move[moveIndex]) {
case 'a':
dx = -1;
dy = 0;
break;
case 'd':
dx = 1;
dy = 0;
break;
case 'w':
dx = 0;
dy = 1;
break;
case 's':
dx = 0;
dy = -1;
break;
default:
break;
}
// if next step is eating the food, do it.
if (mapAI[snakeAIY[i] - dy][snakeAIX[i] + dx] == '$') {
return move[moveIndex];
}
// cannot move backward
else if (snakeAIX[i] + dx == snakeAIX[i - 1] && snakeAIY[i] - dy == snakeAIY[i - 1]) {
distance[moveIndex] = 9999;
}
// cannot move to somewhere not a blank
else if (mapAI[snakeAIY[i] - dy][snakeAIX[i] + dx] != ' '){ /*have already determined if it is '$'*/
distance[moveIndex] = 9999;
}
else{
distance[moveIndex] = abs(foodX - (snakeAIX[i] + dx)) + abs(foodY - (snakeAIY[i] - dy));
}
if (distance[minDistIndex] > distance[moveIndex]) {
minDistIndex = moveIndex;
}
}
if (distance[minDistIndex] == 9999) {
isGameOverAI = 1;
}
return move[minDistIndex];
}
void gameover(void){
if (isGameOverAI) {
printf("You Win!\n");
}else{
printf("You Lose!\n");
}
}