【C语言】井字棋游戏

发布于:2023-01-20 ⋅ 阅读:(12) ⋅ 点赞:(0) ⋅ 评论:(0)

目录

1.头文件game.h

2.源文件

2.1主函数

2.2子函数

3.程序的不足

1.头文件game.h

        可取点:在头文件中,使用#define定义行和列类,在后续的程序中行和列没有具体数值,全部通过ROW和COL表示。这样以后想要对棋盘的大小进行修改的时候,直接在头文件中对#define进行修改即可。

#define ROW 3
#define COL 3

#pragma once

#define ROW 3
#define COL 3

#include<stdio.h>

//菜单函数
void menu();
//是否继续游戏菜单
void ContinueMenu();
//游戏函数
void game();
//初始化棋盘
void InitBoard(char Board[ROW][COL], int row, int col);
//展示棋盘
void DisplayBoard(char Board[ROW][COL], int row, int col);
//玩家下棋
void PlayerMove(char Board[ROW][COL], int row, int col);
//电脑下棋
void ComputerMove(char Board[ROW][COL], int row, int col);
//判断胜、负或平局
char Judge(char Board[ROW][COL], int row, int col);
//判断棋盘是否下满了
int Full(char Board[ROW][COL], int row, int col);

2.源文件

2.1主函数

//井字棋游戏
#include"game.h"

int main()
{
	int input = 0;
	int con = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("开始游戏\n");
			game();
			ContinueMenu();
			printf("请选择:");
			scanf("%d", &con);
			break;
		case 2:
			printf("退出游戏\n");
			break;
		default:
			printf("输入无效,请重新选择\n");
			break;
		}
	}
	while (con == 1 ||(input != 2 && input != 1));
	return 0;
}

2.2子函数

要点

       1. 子函数【2.2棋盘生成函数】,生成的棋盘样式如下图,不知道这样直观的展示出来,会方便理解该程序吗?

        2.子函数【2.3玩家下棋函数】中

        因为数组的起始位置为[0][0],但大众一般认为的起始位置为[1][1],所以要进行+1、-1调整,以符合大众的认知。
        if ((i > 0 && i < row+1 && j > 0 && j < col+1) && (Board[i-1][j-1] == ' '))
        {
            Board[i-1][j-1] = 'O';
           ...

        如果输入的坐标无效,就要重新输入,为此设置了一个标志flag。如果flog=0,说明输入的坐标无效(位置被占用或超出棋盘范围),需要重新输入。

        3.生成随机数

        利用时间戳生成随机数,需要的头文件为#include<stdlib.h>和#include<time.h>,使用rand()函数生成随机数之前,需要先使用srand()函数,生成随机数种子。

#include<stdlib.h>

#include<time.h>

int ran;

srand((unsigned int)time(NULL));

ran = rand();

        4.【2.5判断胜负函数】

        如果是玩家胜利,就返回玩家使用的符号‘O’

        如果是电脑胜利,就返回电脑使用的符号‘X’

        如果是棋盘满了且未分出胜负,就返回‘E’

        如果以上三种情况都不是,就返回'C',继续进行游戏

#define ROW 3
#define COL 3
#include<stdio.h>
#include<time.h>
#include<stdlib.h>

//1.菜单函数
void menu()
{
	printf("************************\n");
	printf("*****1.Play  2.Exit*****\n");
	printf("************************\n");
}


//2.游戏函数
void game()
{
	char result;
	//生成棋盘
	char Board[ROW][COL] = { 0 };
	//初始化棋盘
	InitBoard(Board, ROW, COL);
	//展示棋盘
	DisplayBoard(Board, ROW, COL);
	while (1)
	{
		//玩家下棋
		PlayerMove(Board, ROW, COL);
		DisplayBoard(Board, ROW, COL);
		//判断胜负
		result = Judge(Board, ROW, COL);
			if (result != 'C')
		{
			break;
		}
		//电脑下棋
		ComputerMove(Board, ROW, COL);
		DisplayBoard(Board, ROW, COL);
		//判断胜负
		result = Judge(Board, ROW, COL);
		if (result != 'C')
		{
			break;
		}
	}
	if (result == 'O')
		printf("玩家获胜\n");
	else if (result == 'X')
		printf("电脑获胜\n");
	else
		printf("平局\n");
}


//2.1棋盘初始化函数
void InitBoard(char Board[ROW][COL],int row,int col)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			Board[i][j] = ' ';
		}
	}
}

//2.2棋盘生成函数
void DisplayBoard(char Board[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			//1.打印一行数据
			printf(" %c ", Board[i][j]);
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
		//2.打印分割线
		if (i < row - 1)
		{
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
				printf("|");
			}
			printf("\n");
		}
	}
}

//2.3玩家下棋
void PlayerMove(char Board[ROW][COL], int row, int col)
{
	int i, j;
	int flag = 1;
	printf("玩家回合\n");
	do 
	{
		printf("请输入坐标:");
		scanf("%d%d", &i, &j);
        //因为数组的起始位置为[0][0],但大众一般认为的起始位置为[1][1],所以要进行+1、-1调整
		if ((i > 0 && i < row+1 && j > 0 && j < col+1) && (Board[i-1][j-1] == ' '))
		{
			Board[i-1][j-1] = 'O';
			flag = 1;
		}
		else
		{
            //如果输入的坐标无效,就要重新输入,为此设置了一个标志flag
			printf("坐标无效,请重新输入\n");
			flag = 0;
		}
	}
	while (flag == 0);
}

//2.4电脑下棋
void ComputerMove(char Board[ROW][COL], int row, int col)
{
	int i, j;
	int flag = 1;
	printf("电脑回合\n");
	do 
	{
		//通过时间生成随机位置
		srand((unsigned int)time(NULL));
        //通过模row取余数,就能让i在0~row-1之间浮动;j同理
		i = rand() % row;
		j = rand() % col;
		if (Board[i][j] == ' ')
		{
			Board[i][j] = 'X';
			flag = 1;
		}
		else
			flag = 0;
	}
	while (flag == 0);
}

//2.5判断胜负函数
char Judge(char Board[ROW][COL], int row, int col)
{
	int i, j;
	//判断行是否连成三个
	for (i = 0; i < row; i++)
	{
		int count = 0;
		for (j = 0; j < col-1; j++)
		{
			if ((Board[i][0] != ' ') && (Board[i][j] == Board[i][j + 1]))
			{
				count++;
			}
		}
		if (col-1 == count)
			return Board[i][0];
	}
	//判断列是否连成三个
	for (j = 0; j < col; j++)
	{
		int count = 0;
		for (i = 0; i < row-1; i++)
		{
			if ((Board[0][j] != ' ') && (Board[i][j] == Board[i+1][j]))
			{
				count++;
			}
		}
        //三个元素相等,计数器的数字应该比行数少1。可以用两刀切三段理解。
		if (row - 1 == count)
			return Board[0][j];
	}
	//判断斜线是否连成三个
	if (Board[0][0] == Board[1][1] && Board[2][2] == Board[1][1] && Board[0][0] != ' ')
	return Board[0][0];
	if (Board[0][2] == Board[1][1] && Board[2][0] == Board[1][1] && Board[0][2] != ' ')
	return Board[0][2];
	//判断是否平局
	if (1 == Full(Board, ROW, COL))
	{
		return 'E';
	}
	return 'C';
}

//2.5.1判断棋盘是否满了函数
int Full(char Board[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (Board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}



//3.继续游戏函数
void ContinueMenu()
{
	printf("************************\n");
	printf("游戏已结束,是否继续游戏\n");
	printf("***1.Continue  2.Exit***\n");
	printf("************************\n");
}

3.程序的不足

        程序的不足出现在子函数【2.4电脑下棋】函数中。在实际游玩的发现,在游戏的后期,电脑下棋的速度会变慢。我分析原因如下:

        1.电脑下棋的位置完全靠随机数生成,这就导致在游玩的后期,当大多数格子被占用时,电脑往往需要进行多次循环,才能随机出新的位置,耗费计算资源。

        2.完全随机的落子,也导致电脑下棋没什么策略性,导致玩家很容易胜利,游戏的趣味性降低。  

        如果大家有好的解决方案,欢迎留言!

//2.4电脑下棋
void ComputerMove(char Board[ROW][COL], int row, int col)
{
	int i, j;
	int flag = 1;
	printf("电脑回合\n");
	do 
	{
		//通过时间生成随机位置
		srand((unsigned int)time(NULL));
        //通过模row取余数,就能让i在0~row-1之间浮动;j同理
		i = rand() % row;
		j = rand() % col;
		if (Board[i][j] == ' ')
		{
			Board[i][j] = 'X';
			flag = 1;
		}
		else
			flag = 0;
	}
	while (flag == 0);
}


网站公告

欢迎关注微信公众号

今日签到

点亮在社区的每一天
签到