题目:玩家与电脑在3*3的矩阵中玩三子棋游戏,一方用圈圈(‘O’)表示,另一方用叉叉(‘X’)表示,一旦任一方所执的“棋子”在同一直线(行、列、对角线),则该方获胜,反之,继续游戏,或直到“棋盘”占满为止,则表示平局。编程,用算法实现。
分析:
1、先引入菜单栏,以此为起点,展开整个程序,记录用户选择(玩游戏 or 退出),并跳转至相应的程序中执行
2、以玩游戏为子程序的切入点,并设置相应函数
(1)、设置玩家走棋,电脑走棋两个函数
(2)、分别在两方走棋后显示棋盘上走棋结果
(3)、同时在两方走棋后进行判断,是否一方走棋结束后出现三字连珠情况或者棋盘被落满出现平局的情况
3、在大的框架基础上进行细节上的填充,并对界面进行优化
代码如下:
头文件chess.h
#ifndef _CHESS_H_
#define _CHESS_H_
#include<stdio.h>
#include<Windows.h>
#include<time.h>
#define ROW 3
#define COL 3
#define PLAYER_COLOR 'X'
#define COMPUTER_COLOR 'O'
#pragma warning (disable:4996)
void Game();
void InitBoard(char board[][COL], int row, int col);
void ShowBoard(char board[][COL], int row, int col);
char Judge(char board[][COL], int row, int col);
void PlayerMove(char board[][COL], int row, int col);
void ComputerMove(char board[][COL], int row, int col);
#endif
主函数文件main.c
#include "chess.h"
void ShowMenu() //菜单栏
{
system("cls");
printf("======Welcome play the game=====\n");
printf("================================\n");
printf("======== 1、Play =============\n");
printf("======== 2、Exit =============\n");
printf("================================\n");
printf("================================\n");
printf("Please Select: \n");
}
int main()
{
int select = 0;
int quit = 0;
while (!quit){
ShowMenu();
scanf("%d", &select);
Sleep(500);
system("cls");
switch (select){
case 1:
Game();
break;
case 2:
printf("Bye-bye!\n");
quit = 1;
break;
default:
printf("select error, try again!\n");
break;
}
}
system("pause");
return 0;
}
游戏文件chess.c
#include "chess.h"
void Game()
{
char result = '\0';//char 本质上也是一个整数
char board[ROW][COL];
InitBoard(board, ROW, COL);
srand((unsigned int)time(NULL));//srand种一个随机数种子,一般以事件为种子(time.h)
while (1){
printf("It's turn to you to select point:\n");
PlayerMove(board, ROW, COL);
ShowBoard(board, ROW, COL);
result = Judge(board, ROW, COL);
if (result != 'N'){
break;
}
printf("\n");
printf("It's turn to computer to select point:\n");
ComputerMove(board, ROW, COL);
ShowBoard(board, ROW, COL);
result = Judge(board, ROW, COL);
if (result != 'N'){
break;
}
printf("=====================================================\n");
printf("\n");
}
switch (result){
case 'X'://Player win
printf("You win!\n");
break;
case 'O'://Computer win
printf("You lost!\n");
break;
case 'E'://It ends in a draw 平局
printf("It ends in a draw!\n");
break;
default:
printf("bug?\n");
break;
}
}
// memset(board, ' ', sizeof(board)); 初始化数组board【】【】
void InitBoard(char board[][COL], int row, int col)
{
int i = 0;
for (; i < row; i++){
int j = 0;
for (; j < col; j++){
board[i][j] = ' ';//全部置为空格
}
}
}
void ShowBoard(char board[][COL], int row, int col)
{
for (row = 0; row < ROW; row++){
for (col = 0; col < COL; col++){
printf("| %c \t", board[row][col]);
}
printf("\n-----------------------\n");
}
}
void PlayerMove(char board[][COL], int row, int col)
{
while (1){
int x = 0;
int y = 0;
printf("Please input Pos<x,y>: \n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= 3 && y >= 1 && y <= 3){ //Player输入的坐标要求在棋盘内
if (board[x - 1][y - 1] == ' '){ //判断该位置是否已经被占了
board[x - 1][y - 1] = PLAYER_COLOR;
break;
}
else{
printf("Enter error, Try again: \n");
}
}
}
}
void ComputerMove(char board[][COL], int row, int col)
{
while (1){
int x = GetRandom(1,3); //随机生成电脑落子的横纵坐标
int y = GetRandom(1,3);
if (board[x - 1][y - 1] == ' '){ //判断随机产生的位置是否已经被占了
board[x - 1][y - 1] = COMPUTER_COLOR;
printf("The point selected by computer is Pos<%d,%d>.\n", x, y);
break;
}
}
}
int GetRandom(int start, int end){
//[start,end]
return rand() % (end - start + 1) + start;//万能公式,求一随机区间生成的随机数
}
char Judge(char board[][COL], int row, int col)
{
int i, j;
for (i = 0; i < ROW; i++){//若三字连珠,则返回'X'或'O',表示胜利方所执的棋
for (i = 0; i < row; i++){ //行
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1]!=' ')
return board[i][0];
}
for (i = 0; i < col; i++){//列
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
return board[0][i];
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' '){ //对角线
return board[0][0];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' '){ //对角线
return board[0][0];
}
}
if (IsFull(board, ROW, COL)){ //若执行到此步骤,表明没有获胜方,下面判断棋盘是否满了
return 'E'; //满了,平局
}
else{
return 'N'; //未满,NEXT,继续
}
}
int IsFull(char board[ROW][COL], int row, int col){ //0--了满;1--未满
int i, j;
for (i = 0; i < ROW; i++){
for (j = 0; j < COL; j++){
if (board[ROW][COL] == ' '){
return 1;
}
}
}
return 0;
}
涉及的知识点:
一、分文件书写形式:
需要至少定义两个版块:一个文件名以 .h 结尾,放置函数的声明,具体格式为:
#ifndef _TEST_H_
#define _TEST_H_
//函数的声明
//.......
#endif //_TEST_H_
l另一个文件名以 .c 结尾,放置函数的实现,即为函数的内容,需要注意的时,在该文件的顶端,需要和头文件进行连接 ,格式为:
#include "test.h"
二、
#include<windows.h>
system("cls"); //清屏操作,将命令行窗口中的内容清空
Sleep(); //休眠函数,表示系统暂停时间长短,也可以理解为延时操作,括号内加时间数,单位为毫秒
三、随机数的生成
虽说称之为随机数,但是它从某种意义上来说并不是随机的,是伪随机数,是根据一个数(我们可以称它为种子)为基准以某个递推公式推算出来的一系列数,当这系列数很大的时候,就符合正态分布,从而相当于产生了随机数,但这不是真正的随机数,只能说明是在一定的区间内看似随机!
srand() 用来设置 rand() 产生随机数时的随机数种子。参数 seed 必须是个整数,如果每次 seed 都设相同值,rand() 所产生的随机数值每次就会一样。
rand() 产生的随机数在每次运行的时候都是与上一次相同的。若要不同, 用函数 srand() 初始化它。可以利用 srand((unsigned int)(time(NULL)) 的方法,产生不同的随机数种子,因为每一次运行程序的时间是不同的。
还有,在一定范围内,任意区间【start,end】随机数求取公式为 rand()%(end-start)+start