0
点赞
收藏
分享

微信扫一扫

三子棋作业练习-C语言

逸省 2022-04-25 阅读 42
c语言
  • 本项目分2个模块
    • 测试模块 源文件test.c
    • 游戏模块 头文件game.c 源文件game.h
  • 完整代码如下
//test.c   测试模块

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

void menu()    //菜单函数.3,由test()函数调用
{
	printf("******************************\n");
	printf("*********1.play   0.exit******\n");
	printf("******************************\n");
}

//功能模块化,增强扩展性——使用ganme.c和game.h文件来存放实现游戏功能的代码。然后在game()函数中直接调用即可
void game()    //游戏函数.4,由test()函数调用。核心函数。
{
	char ret = 0;  //创建ret接收返回值

	char board[ROW][COL] = { 0 };  	 //申明数组,存储棋盘信息
									 //使用了game.h中的字符,记得引用对应头文件

	//将需要实现的步骤函数化,通过传参数来调用函数以实现需要的功能,如下
	
	InitBoard(board, ROW, COL);     //初始化棋盘.4.1,本质上为初始化数组,把数组,数组的行数列数都作为参数传过去  
									//函数调用,本函数属于游戏模块的相关代码,函数调用要成功,就要在game.h中定义,在game.c中实现
					
	DisplayBoard(board, ROW, COL);   //打印棋盘.4.2,本质上是打印数组,只不过我们对数组进行了一些修饰

	//下棋
	while (1)
	{
		//玩家下棋
		PlayerMove(board, ROW, COL);   //玩家走一步.4.3
		DisplayBoard(board, ROW, COL);   //打印棋盘

		//判断玩家是否赢.4.5
		ret = Iswin(board, ROW, COL);    
		if (ret != 'C')
		{
			break;           //如果游戏不能继续玩了,直接跳出循环判断输赢即可
		}

		//电脑下棋
		ComputerMove(board, ROW, COL);  //电脑走一步.4.4
		DisplayBoard(board, ROW, COL);    //打印

		//判断电脑是否赢
		ret = Iswin(board, ROW, COL);
		if (ret != 'C')
		{
			break;           //如果游戏不能继续玩了,直接跳出循环判断输赢即可
		}
	}

	if (ret == '*')
	{
		printf("玩家赢\n");
		printf("\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢\n");
		printf("\n");
	}
	else 
	{
		printf("平局\n");
		printf("\n");
	}
}

void test()   //测试函数.2,由主函数调用
{
	int input = 0;

	//此处设置随机数生成器srand,是为了项目某处需要生成随机数时,直接使用rand函数调用srand。避免需要随机数时频繁的设置srand
 	srand((unsigned int)time(NULL));  //设置随机数生成器srand的时候,拿时间戳(time函数)来设置
								      //time函数返回的是一个time-t的值,此处需要将它强制转换类型。time函数的参数设置为空指针
	                                  //使用srand函数和time函数需要引用对应头文件

	do     //显示菜单界面,玩家输入数字可进入对应游戏模式
	{
		menu();   //菜单函数.3

		printf("请选择:>");
		scanf("%d", &input);

		switch (input)
		{
			case 1:
				game();    //游戏函数.4
				break;
			case 0:
				printf("退出游戏\n");
				break;
			default:
				printf("重新选择!\n");
				break;
		}
	} while (input);
}

int main()    //主函数.1
{
	test();   //调用测试函数.2
	return 0;
}
//game.h   游戏模块
#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define ROW 3
#define COL 3

void InitBoard(char board[ROW][COL], int row, int col);   //初始化棋盘.4.1

void DisplayBoard(char board[ROW][COL], int row, int col);   //打印棋盘.4.2

void PlayerMove(char board[ROW][COL], int row, int col);   //玩家下棋移动.4.3

void ComputerMove(char board[ROW][COL], int row, int col);    //电脑移动.4.4

//告诉我们4种游戏的状态
//玩家赢 ‘*’
//电脑赢  ‘#’
//平局   'Q'
//继续  'C'
char Iswin(char board[ROW][COL], int row, int col);   //返回游戏当前输赢状态.4.5

char IsFull(char board[ROW][COL], int row, int col);   //返回棋盘是否满格状态.4.6
													   //此处其实不需要申明IsFull(),写上去只为了整理思路
//game.c  游戏模块
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

//初始化棋盘.4.1:把棋盘上的每个数组元素都初始化为“空格”

//   |   |   
//---|---|---
//   |   |   
//---|---|---
//   |   |   

void InitBoard(char board[ROW][COL], int row, int col)
{
	int i = 0, j = 0;

	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

//打印棋盘.4.2
//观察棋盘得出:棋盘是一行数据一行分割行的循环,但是最后一组循环不要分割行,用for循环实现,加条件使得到最后一行的时候不执行打印分割行的代码
//优化前的代码如下
void DisplayBoard(char board[ROW][COL], int row, int col)  
{
	int i = 0;

	for (i = 0; i < row; i++)   
	{
		printf(" %c | %c | %c \n",board[i][0], board[i][1], board[i][2]);   //打印一行的数据 
																			//以%c的格式输出后面这三个数据
// 
		if (i < row - 1)
		{
			printf("---|---|---\n");    //打印分割行
		}
	
	}
}

//(显然,这种写法过于死板,观察printf(" %c | %c | %c \n",board[i][0], board[i][1], board[i][2]);和printf("---|---|---\n");这2行代码写定了行数,
//对于三子棋足以,但一旦需要五子棋等需要更多棋盘格子的明显不能满足,此写法太暴力(挫),需要进行优化,如下

void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i = 0, j = 0;

	for (i = 0; i < row; i++)     //是<不是<=
	{
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			
			if (j < col - 1)
			{
				printf("|");
			}
		}
		printf("\n");

		if (i < row - 1)
		{
			for (j = 0; j < col; j++)
			{
				printf("---");
				
				if (j < col - 1)
				{
					printf("|");
				}
			}
			printf("\n");
		}
	}
}

//玩家下棋.4.3
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0, y = 0;

	printf("玩家走:>\n");

	while (1)
	{
		printf("请输入要下的坐标:>\n");
		scanf("%d%d", &x, &y);

		//判断输入的x,y坐标的合法性
		if (x >= 1 && x <= row && y >= 1 && y <= col)    // 此时判断是站在玩家角度,范围是1-row,1-col  
		{
			if (board[x - 1][y - 1] == ' ')       
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("该坐标被占用\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入:>\n");
		}
	}
}

//电脑走.4.4
void ComputerMove(char board[ROW][COL], int row, int col)     
{
	int x = 0, y = 0;

	printf("电脑走:>\n");       //随机走,需要随机生成一个坐标,找一个随机的位置,此位置未被占用

	while (1)
	{
		x = rand() % row;     //rand用来生成随机数,生成的随机数的范围是0-randmax,我们需要的范围是0-2(0.1.2),只需给rand模row即可  
							  //使用rand函数需要调用srand随机数生成器,在测试模块test()中已设置srand,此处直接调用  
		y = rand() % col;	  //此时(x,y)就是一个随机坐标,范围在(0.0)-(2.2)

	   //判断坐标是否合法
		if (board[x][y] == ' ')        //如果此处没有棋子,则下棋   是==不是=
		{
			board[x][y] = '#';
			break;
		}
		//如果此处有棋子,则重新生成随机坐标,再判断
	}
}

//判断棋格是否满.4.6,为判断是否为平局做铺垫
char IsFull(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;

	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
			{
				return 0;   //没满
			}
		}
	}
	return 1;  //满
}

//判断输赢.4.5
char Iswin(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	
	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][1];
		}
	}

	for (j = 0; j < col; j++)   //竖三列
	{
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
		{
			return board[1][j];
		}
	}

	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ') //对角线
	{
		return board[1][1];
	}

	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
	{
		return board[1][1];
	}

	//判断平局.4.6
	if (1 == IsFull(board, ROW, COL))
	{
		return 'Q';
	}

	return 'C';       
}
举报

相关推荐

【c语言】三子棋

C语言三子棋

三子棋(C 语言)

三子棋C语言

三子棋(C语言)

C语言编写三子棋

0 条评论