编程 stat == 字符数组 之前 %d 写法 oar can
今天要完成一个相对于之前学习更有挑战性的小程序——三子棋。
相信我们大部分人都接触过三子棋,这是一款操作简单易上手的小游戏。
先简单介绍一下三子棋的规则,方便我们接下来的编程和理解。规则如下:
在九宫格棋盘上,只要将自己的三个棋子走成一条线(横、竖、对角线),对方就算输了。
规则很简单,但是我们应该从哪里入手完成这个三子棋程序呢?
首先,我们的游戏程序应该先有个菜单页面,这个菜单页面用来让用户操作选择玩游戏,或是退出。
界面可以很简单,只需要几条 printf 语句即可。
这里我们尽可能用函数来完成游戏的功能:
- void menu()
- {
- printf("***************************************\n");
- printf("* 1.play 0.exit *\n");
- printf("***************************************\n");
- }
这就是一个简单的主菜单界面,效果如下:
既然菜单中有选项,我们就必须要设计一个变量用来接收用户的选择。
而且游戏程序本身应该允许用户反复进行玩耍,所以在主函数中,我们需要用一个循环来完成这个功能。
do-while循环在调用时会先运行循环体,而后在进行判断,所以这里我们选择使用do-while循环:
- int main()
- {
- int choice;
- do
- {
- menu();
- printf("Input your choice:");
- scanf("%d", &choice);
- switch (choice)
- {
- case 1:
- game();
- break;
- case 0:
- break;
- default:
- printf(" Input error!Please try again.\n");
- break;
- }
- } while (choice);
- return 0;
- }
由于用户选择选项1时我们需要为用户启动游戏程序,所以这里我们使用一个switch语句来接受用户的选择。
选择0时退出程序,所以我们只需要跳出循环,即可退出。
而输入0、1之外的值时,我们应该向用户报输入错误,所以在default中输出一条报错信息。
接下来就是我们程序的重点——三子棋游戏本身了。
先创建一个game()函数,里面的内容我们一步步来填充。
- void game()
- {
- }
在程序开始阶段,我们首先要创建一个3*3的二维字符数组,
由于长和宽我们要经常用到,为了后续修改方便,我们采用宏定义方式:
- #define ROWS 3
- #define COLS 3
接下来在game()函数中创建数组:
- char board[ROWS][COLS];
并将这个数组进行初始化,因为这个数组在后续需要输出展示在用户面前,所以我们将值初始化为空格“ ”。
初始化用函数进行完成:
- void init_board(char board[ROWS][COLS], int rows, int cols)
- {
- int i, j;
- for (i = 0; i < rows; i++)
- {
- for (j = 0; j < cols; j++)
- {
- board[i][j] = ‘ ‘;
- }
- }
- }
接下来,我们应该输出这个数组棋盘,来检查一下是否初始化完成,
但我们没有展示棋盘的函数,所以我们需要完成这个显示棋盘函数:
- void show_board(char board[ROWS][COLS], int rows, int cols)
- {
- int i;
- for (int i = 0; i < rows; i++)
- {
- printf(" %c | %c | %c \n",board[i][0],board[i][1],board[i][2]);
- if (i != rows - 1)
- printf(" ---|---|--- \n");
- }
- }
这里需要利用循环来输出我们棋盘的格式,格式不统一,可以根据自己的喜好进行修改。
下面展示一下我这个代码所输出的棋盘:
上面已经看出我的棋盘初始化已经完成,所以接下来我们需要考虑如何让电脑或用户进行下棋操作了。
电脑走需要让电脑产生随机坐标,然后在数组的这个坐标位置放入一个“X”作为电脑的棋子。
所以代码如下:
- void ComputerMove(char board[ROWS][COLS], int rows, int cols)
- {
- int x, y;
- printf("Compter‘s turn to move:\n");
- while (1)
- {
- x = rand() % rows;
- y = rand() % cols;
- if (board[x][y] == ‘ ‘)
- {
- board[x][y] = ‘X‘;
- break;
- }
- }
- }
rand()是用来生成随机数的,这里我们还需要在主函数main中加上一行代码。
由于我们不希望他多次生成随机数,生成一次就足够用了,所以直接在创建choice变量的下一行加上下面这个代码即可:
- srand((unsigned int) time(NULL));
注意生成随机数需要引用time.h这个头文件。
电脑下完棋后,需要轮到我们的用户进行下棋操作,这个函数和电脑下棋大同小异,
但是要注意人的习惯不会输入(0,0)这个坐标,而是输入(1,1)。
所以这里我们要给传过去的参数-1。
解决这个问题后的代码如下:
- void player_move(char board[ROWS][COLS], int rows, int cols)
- {
- int x, y;
- printf("Player‘s turn to move:\n");
- while (1)
- {
- printf("Input x and y(like x y):\n");
- scanf("%d %d", &x, &y);
- if (x >= 1 && x <= rows && y >= 1 && y <= cols)
- {
- if (board[x - 1][y - 1] == ‘ ‘)
- {
- board[x - 1][y - 1] = ‘O‘;
- break;
- }
- else printf("The location has been taken!Please try again.\n");
- }
- else printf(" Input error!Please try again.\n");
- }
- }
在双方走完后,我们需要判断是否胜利,也就是判断之前我们提到的规则,
这时我们需要编写一个checkwin()函数来检测并返回一个值表示谁获胜。
代码如下:
- char check_win(char board[ROWS][COLS], int rows, int cols)
- {
- int i;
- for (i = 0; i < rows; i++)
- {
- if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ‘ ‘)
- return board[i][1];
- }
- for (i = 0; i < cols; i++)
- {
- if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ‘ ‘)
- return board[1][i];
- }
- if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ‘ ‘)
- return board[1][1];
- else if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ‘ ‘)
- return board[1][1];
- else if (is_full(board, rows, cols))
- return ‘q‘;
- return 0;
- }
由于可能出现棋盘下满,却没人获胜的情况,
所以我们需要在其中判断一下平局的情况,
这里我们编写了一个is_full()函数,用来判断棋盘是否下满:
- static int is_full(char board[ROWS][COLS], int rows, int cols)
- {
- int i, j;
- for (i = 0; i < rows; i++)
- {
- for (j = 0; j < cols; j++)
- {
- if (board[i][j] == ‘ ‘)
- return 0;
- }
- }
- return 1;
- }
注意这个函数我们只在checkwin中会使用到,我们并不希望它在其他源文件的函数中被使用,所以我们加上了static。
这时程序的雏形已经基本完成,我们只需要按我们自己理解的游戏步骤来完成game()函数即可。
所以完成后的game()函数如下所示:
- void game()
- {
- char win = 0;
- char arr[ROWS][COLS];
- init_board(board, ROWS, COLS);
- do
- {
- computer_move(board, ROWS, COLS);
- show_board(board, ROWS, COLS);
- win = check_win(board, ROWS, COLS);
- if (win != 0)
- break;
- player_move(board, ROWS, COLS);
- show_board(board, ROWS, COLS);
- win = check_win(board, ROWS, COLS);
- } while (win == 0);
- if (win == ‘X‘)
- printf("You lose!Good luck next time!\n");
- if (win == ‘O‘)
- printf("You win!Congratulations!\n");
- if (win == ‘q‘)
- printf("The score was tied!Good luck next time!\n");
- }
这样,将上面各个部分合在一起,这个程序就被我们完成了。
下面放上我自己写的,比较丑陋的代码:
我的代码分为三部分,
第一部分是头文件:
- #ifndef __CHESS_H__
- #define __CHESS_H__
- #include<stdio.h>
- #include<time.h>
- #include<Windows.h>
- #define ROWS 3
- #define COLS 3
- void show_board(char board[ROWS][COLS], int rows, int cols);
- void init_board(char board[ROWS][COLS], int rows, int cols);
- void computer_move(char board[ROWS][COLS], int rows, int cols);
- void player_move(char board[ROWS][COLS], int rows, int cols);
- char check_win(char board[ROWS][COLS], int rows, int cols);
- # endif//__CHESS_H__
第二部分是源文件的函数部分:
- #include"3chess.h"
- void show_board(char board[ROWS][COLS], int rows, int cols)
- {
- int i;
- for (int i = 0; i < rows; i++)
- {
- printf(" %c | %c | %c \n",board[i][0],board[i][1],board[i][2]);
- if (i != rows - 1)
- printf(" ---|---|--- \n");
- }
- }
- void init_board(char board[ROWS][COLS], int rows, int cols)
- {
- int i, j;
- for (i = 0; i < rows; i++)
- {
- for (j = 0; j < cols; j++)
- {
- board[i][j] = ‘ ‘;
- }
- }
- }
- void computer_move(char board[ROWS][COLS], int rows, int cols)
- {
- int x, y, i;
- printf("Compter‘s turn to move:\n");
- while (1)
- {
- x = rand() % rows;
- y = rand() % cols;
- for (i = 0; i < rows; i++)
- {
- if (board[i][0] == board[i][1] && board[i][0] == ‘X‘ && board[i][2] == ‘ ‘)
- {
- board[i][2] = ‘X‘;
- goto flag1;
- }
- else if (board[i][1] == board[i][2] && board[i][1] == ‘X‘ && board[i][0] == ‘ ‘)
- {
- board[i][0] = ‘X‘;
- goto flag1;
- }
- else if (board[i][0] == board[i][2] && board[i][2] == ‘X‘ && board[i][1] == ‘ ‘)
- {
- board[i][1] = ‘X‘;
- goto flag1;
- }
- else if (board[0][i] == board[1][i] && board[0][i] == ‘X‘ && board[2][i] == ‘ ‘)
- {
- board[2][i] = ‘X‘;
- goto flag1;
- }
- else if (board[1][i] == board[2][i] && board[1][i] == ‘X‘ && board[0][i] == ‘ ‘)
- {
- board[0][i] = ‘X‘;
- goto flag1;
- }
- else if (board[0][i] == board[2][i] && board[2][i] == ‘X‘ && board[1][i] == ‘ ‘)
- {
- board[1][i] = ‘X‘;
- goto flag1;
- }
- else if (board[0][0] == board[1][1] && board[0][0] == ‘X‘ && board[2][2] == ‘ ‘)
- {
- board[2][2] = ‘X‘;
- goto flag1;
- }
- else if (board[1][1] == board[2][2] && board[1][1] == ‘X‘ && board[0][0] == ‘ ‘)
- {
- board[0][0] = ‘X‘;
- goto flag1;
- }
- else if (board[0][0] == board[2][2] && board[0][0] == ‘X‘ && board[1][1] == ‘ ‘)
- {
- board[1][1] = ‘X‘;
- goto flag1;
- }
- else if (board[0][2] == board[1][1] && board[1][1] == ‘X‘ && board[2][0] == ‘ ‘)
- {
- board[2][0] = ‘X‘;
- goto flag1;
- }
- else if (board[1][1] == board[2][0] && board[1][1] == ‘X‘ && board[0][2] == ‘ ‘)
- {
- board[0][2] = ‘X‘;
- goto flag1;
- }
- else if (board[2][0] == board[0][2] && board[2][0] == ‘X‘ && board[1][1] == ‘ ‘)
- {
- board[1][1] = ‘X‘;
- goto flag1;
- }
- }
- for (i = 0; i < rows; i++)
- {
- if (board[i][0] == board[i][1] && board[i][0] == ‘O‘ && board[i][2] == ‘ ‘)
- {
- board[i][2] = ‘X‘;
- goto flag1;
- }
- else if (board[i][1] == board[i][2] && board[i][1] == ‘O‘ && board[i][0] == ‘ ‘)
- {
- board[i][0] = ‘X‘;
- goto flag1;
- }
- else if (board[i][0] == board[i][2] && board[i][2] == ‘O‘ && board[i][1] == ‘ ‘)
- {
- board[i][1] = ‘X‘;
- goto flag1;
- }
- else if (board[0][i] == board[1][i] && board[0][i] == ‘O‘ && board[2][i] == ‘ ‘)
- {
- board[2][i] = ‘X‘;
- goto flag1;
- }
- else if (board[1][i] == board[2][i] && board[1][i] == ‘O‘ && board[0][i] == ‘ ‘)
- {
- board[0][i] = ‘X‘;
- goto flag1;
- }
- else if (board[0][i] == board[2][i] && board[2][i] == ‘O‘ && board[1][i] == ‘ ‘)
- {
- board[1][i] = ‘X‘;
- goto flag1;
- }
- else if (board[0][0] == board[1][1] && board[0][0] == ‘O‘ && board[2][2] == ‘ ‘)
- {
- board[2][2] = ‘X‘;
- goto flag1;
- }
- else if (board[1][1] == board[2][2] && board[1][1] == ‘O‘ && board[0][0] == ‘ ‘)
- {
- board[0][0] = ‘X‘;
- goto flag1;
- }
- else if (board[0][0] == board[2][2] && board[0][0] == ‘O‘ && board[1][1] == ‘ ‘)
- {
- board[1][1] = ‘X‘;
- goto flag1;
- }
- else if (board[0][2] == board[1][1] && board[1][1] == ‘O‘ && board[2][0] == ‘ ‘)
- {
- board[2][0] = ‘X‘;
- goto flag1;
- }
- else if (board[1][1] == board[2][0] && board[1][1] == ‘O‘ && board[0][2] == ‘ ‘)
- {
- board[0][2] = ‘X‘;
- goto flag1;
- }
- else if (board[2][0] == board[0][2] && board[2][0] == ‘O‘ && board[1][1] == ‘ ‘)
- {
- board[1][1] = ‘X‘;
- goto flag1;
- }
- }
- if (board[x][y] == ‘ ‘)
- {
- board[x][y] = ‘X‘;
- goto flag1;
- }
- }
- flag1:;
- }
- void player_move(char board[ROWS][COLS], int rows, int cols)
- {
- int x, y;
- printf("Player‘s turn to move:\n");
- while (1)
- {
- printf("Input x and y(like x y):\n");
- scanf("%d %d", &x, &y);
- if (x >= 1 && x <= rows && y >= 1 && y <= cols)
- {
- if (board[x - 1][y - 1] == ‘ ‘)
- {
- board[x - 1][y - 1] = ‘O‘;
- break;
- }
- else printf("The location has been taken!Please try again.\n");
- }
- else printf(" Input error!Please try again.\n");
- }
- }
- static int is_full(char board[ROWS][COLS], int rows, int cols)
- {
- int i, j;
- for (i = 0; i < rows; i++)
- {
- for (j = 0; j < cols; j++)
- {
- if (board[i][j] == ‘ ‘)
- return 0;
- }
- }
- return 1;
- }
- char check_win(char board[ROWS][COLS], int rows, int cols)
- {
- int i;
- for (i = 0; i < rows; i++)
- {
- if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ‘ ‘)
- return board[i][1];
- }
- for (i = 0; i < cols; i++)
- {
- if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ‘ ‘)
- return board[1][i];
- }
- if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ‘ ‘)
- return board[1][1];
- else if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ‘ ‘)
- return board[1][1];
- else if (is_full(board, rows, cols))
- return ‘q‘;
- return 0;
- }
这一部分是经过发挥的,让电脑更智能,但代码部分我并没有想出简化的写法,只好一步步的用if语句进行完成了。
第三部分是源文件的游戏测试部分:
- #include"3chess.h"
- void menu()
- {
- printf("***************************************\n");
- printf("* 1.play 0.exit *\n");
- printf("***************************************\n");
- }
- void first_move()
- {
- printf("***************************************\n");
- printf("* 1.computer first 2.player first *\n");
- printf("***************************************\n");
- }
- void game()
- {
- int choice_1, win;
- char board[ROWS][COLS];
- init_board(board, ROWS, COLS);
- first_move();
- flag:
- printf("Input your choice;");
- scanf("%d", &choice_1);
- switch (choice_1)
- {
- case 1:
- do
- {
- computer_move(board, ROWS, COLS);
- show_board(board, ROWS, COLS);
- win = check_win(board, ROWS, COLS);
- if (win != 0)
- break;
- player_move(board, ROWS, COLS);
- show_board(board, ROWS, COLS);
- win = check_win(board, ROWS, COLS);
- } while (win == 0);
- if (win == ‘X‘)
- printf("You lose!Good luck next time!\n");
- if (win == ‘O‘)
- printf("You win!Congratulations!\n");
- if (win == ‘q‘)
- printf("The score was tied!Good luck next time!\n");
- break;
- case 2:
- do
- {
- show_board(board, ROWS, COLS);
- player_move(board, ROWS, COLS);
- show_board(board, ROWS, COLS);
- win = check_win(board, ROWS, COLS);
- if (win != 0)
- break;
- computer_move(board, ROWS, COLS);
- win = check_win(board, ROWS, COLS);
- } while (win == 0);
- if (win == ‘X‘)
- printf("You lose!Good luck next time!\n");
- if (win == ‘O‘)
- printf("You win!Congratulations!\n");
- if (win == ‘q‘)
- printf("The score was tied!Good luck next time!\n");
- break;
- default:
- printf(" Input error!Please try again.\n");
- goto flag;
- }
- }
- int main()
- {
- int choice;
- srand((unsigned int)time(NULL));
- do
- {
- menu();
- printf("Input your choice:");
- scanf("%d", &choice);
- switch (choice)
- {
- case 1:
- game();
- break;
- case 0:
- break;
- default:
- printf(" Input error!Please try again.\n");
- break;
- }
- } while (choice);
- return 0;
- }
这一部分,我加入了让用户选择电脑先走或者用户先走的功能,使用户的游戏体验更好。
以上就是我的代码,希望各位能帮助我进行优化改进。
用C语言完成:三子棋。
来源: http://www.bubuko.com/infodetail-2361900.html