C语言从0到1之《三子棋》的实现

news/2024/5/18 16:36:45 标签: c语言, c++, 游戏程序

 

🕺作者@启明星使

🎃专栏:《数据库》《C语言》

🏇分享一句话:

沉香:差一点,怎么总是差一点

杨戬:一定是练功的时候总是差不多,到了关键的时候就是差一点

大家一起加油🏄‍♂️🏄‍♂️🏄‍♂️

希望得到大家的支持,如果有帮助希望得到的大家三连~~~afbae359ff6c469aa4242bd6dcb5e558.jpeg

 

前言

新手小白想学好编程,一定要注重代码实现

所以今天我将带领大家写一个小游戏《三子棋》

需要具备的知识有循环·数组·函数

是不是都学过了呢?

那么我们来动手实操检验一下成果~~~

思路

  1. 首先我们要有个菜单,选择开始或者退出

  2. 我们要有个井字格来划分区域

  3. 我们要能下棋

  4. 电脑要和我们对局

  5. 要判断是否胜利

具体实现

菜单

void memu() {
    printf("********************************\n");
    printf("************* 1->开始 **********\n");
    printf("************* 0->退出 **********\n");
    printf("********************************\n");
    printf("->");
}

这里我们用到printf打印一个界面

接下来就要输入1或者0来选择

是不是非常简单,我们接着往下看~

主函数

一个switch语句进行选择

int main() {
    memu();
    srand((unsigned int)time(NULL));//电脑随机下棋,后续会有解释
    int input;
    scanf("%d", &input);
    switch(input) {
    case 0:
        exit(0);//强制退出程序
        break;
    case 1:
        game();//后续接着进入游戏
        break;
    default:
        printf("输入错误!");
        break;
    }
​
}
 

初始化数组

我们要使用一个char型数组来存储棋子

先将数组初始化

void Init(char board[ROW][COL], int row, int col) {
    for (int i=0; i < row; i++) {
        for (int j=0; j < col; j++) {
            board[i][j] = ' ';
        }
    }
}

打印界面

我们定义一个函数专门打印界面

打印用数组存储下的棋

以及分割的符号

我们定义row为行,col为列

void print(char board[ROW][COL], int row, int col) {
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            printf(" %c ", board[i][j]);
            if (j<col-1) {
                printf("|");
            }
        }
        printf("\n");
        if (i < row - 1)
        {
            for (int j = 0; j < col; j++)
            {
                printf("---");
                if (j < col - 1)
                    printf("|");
            }
            printf("\n");
        }
    }
}

接下来我们就要开始下棋了

tip:玩家为* 电脑为#

玩家先手

这里我们要考虑几个问题:

  1. 输入的坐标并不是数组的下标

  2. 输入坐标超过数组的界限怎么办

void player_move(char board[ROW][COL], int row, int col) {
    while (1)
    {
        printf("请输入要下棋的坐标:>");
        int x = 0;
        int y = 0;
        scanf("%d %d", &x, &y);
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        //在这里我们判断是否在数组内
        {
            if (board[x - 1][y - 1] == ' ')
            {
                board[x - 1][y - 1] = '*';
                //判断该位置为空则可以下,否则位置错误重新输入
                break;
            }
            else
            {
                printf("坐标错误\n");
            }
        }
        else
        //如果不在数组内则位置错误,重新输入
        {
            printf("坐标错误\n");
        }
    }
}

判断棋盘是否满了

在对局中我们每次下棋都要判断棋盘是否满了

如果已经满了还未分出胜负,则为平局

void is_full(char board[ROW][COL], int row, int col) {
    int flag = 0;
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            if (board[i][j] == ' ') {
                flag++;
            }
        }
    }
    if (flag == 0) {
        printf("平局\n");
        exit(0);
    }
}

电脑对局

在这里我们用随机数的方式实现电脑下棋

void computer_move(char board[ROW][COL], int row, int col) {
    printf("AI下棋:\n");
    while (1) {
        is_full(board, ROW, COL);
        int x = rand() % row;
        int y = rand() % col;
        //使用rand()函数
        //之前我们使用srand((unsigned int)time(NULL))
        //就是以时间来求随机数以求更随机
        if (board[x][y] == ' ') {
            board[x][y] = '#';
            break;
        }
    }
}

判断胜负

三子棋的规则是什么?

三个相同的棋在同行同列或者对角线上即为胜利

char is_win(char board[ROW][COL], int row, int col) {
    for (int i = 0; i < row; i++)
    {
        if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
        {
            return board[i][0];
        }
    }
    for (int i = 0; i < col; i++)
    {
        if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
        {
            return board[0][i];
        }
    }
    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];
    }
    is_full(board, ROW, COL);
}

这里我们返回符合条件的*或者#,在game()函数中判断返回值,即可判断胜利

game()函数

使用一个循环,如果有一方胜利或者平局则打破循环结束游戏

void game() {
    char board[ROW][COL];
    char res = 0;
    Init(board, ROW, COL);
    print(board, ROW, COL);
    while (1) {
        player_move(board, ROW, COL);
        print(board, ROW, COL);
        is_win(board, ROW, COL);
        Sleep(1000);
        computer_move(board, ROW, COL);
        print(board, ROW, COL);
        is_win(board, ROW, COL);
        res= is_win(board, ROW, COL);
        if (res == '*') {
            printf("玩家胜!\n");
            break;
        }
        else if(res=='#') {
            printf("AI胜!\n");
            break;
        }
    }
}

 

总结

在写代码的过程中,遇到问题解决问题是提升最快的方式。

当你碰到不会的,不懂的,不要害怕,这正是你所能够进步的地方!

我是分模块写的,源码如下:

fun.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "sanziqi.h"
void memu() {
	printf("********************************\n");
	printf("************* 1->开始 **********\n");
	printf("************* 0->退出 **********\n");
	printf("********************************\n");
	printf("->");
}

void game() {
	char board[ROW][COL];
	char res = 0;
	Init(board, ROW, COL);
	print(board, ROW, COL);
	while (1) {
		player_move(board, ROW, COL);
		print(board, ROW, COL);
		is_win(board, ROW, COL);
		Sleep(1000);
		computer_move(board, ROW, COL);
		print(board, ROW, COL);
		is_win(board, ROW, COL);
		res= is_win(board, ROW, COL);
		if (res == '*') {
			printf("玩家胜!\n");
			break;
		}
		else if(res=='#') {
			printf("AI胜!\n");
			break;
		}
	}
}
void Init(char board[ROW][COL], int row, int col) {
	for (int i=0; i < row; i++) {
		for (int j=0; j < col; j++) {
			board[i][j] = ' ';
		}
	}
}
void print(char board[ROW][COL], int row, int col) {
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < col; j++) {
			printf(" %c ", board[i][j]);
			if (j<col-1) {
				printf("|");
			}
		}
		printf("\n");
		if (i < row - 1)
		{
			for (int j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");
		}
	}
}
void player_move(char board[ROW][COL], int row, int col) {
	while (1)
	{
		printf("请输入要下棋的坐标:>");
		int x = 0;
		int y = 0;
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("坐标错误\n");
			}
		}
		else
		{
			printf("坐标错误\n");
		}
	}
	

}
void computer_move(char board[ROW][COL], int row, int col) {
	printf("AI下棋:\n");
	while (1) {
		is_full(board, ROW, COL);
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ') {
			board[x][y] = '#';
			break;
		}
	}
}
char is_win(char board[ROW][COL], int row, int col) {
	for (int i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
		{
			return board[i][0];
		}
	}
	for (int i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
		{
			return board[0][i];
		}
	}
	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];
	}
	is_full(board, ROW, COL);
}
void is_full(char board[ROW][COL], int row, int col) {
	int flag = 0;
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < col; j++) {
			if (board[i][j] == ' ') {
				flag++;
			}
		}
	}
	if (flag == 0) {
		printf("平局\n");
		exit(0);
	}
}

main.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "sanziqi.h"
int main() {
	memu();
	srand((unsigned int)time(NULL));
	int input;
	scanf("%d", &input);
	switch(input) {
	case 0:
		exit(0);
		break;
	case 1:
		game();
		break;
	default:
		printf("输入错误!");
		break;
	}

}

sanziqi.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define ROW 3
#define COL 3
void memu();//菜单
void game();//进入游戏
void Init(char board[ROW][COL], int row, int col);//初始化
void print(char board[ROW][COL],int row,int col);//打印界面
void player_move(char board[ROW][COL], int row, int col);//玩家下棋
void computer_move(char board[ROW][COL], int row, int col);//AI下棋
char is_win(char board[ROW][COL], int row, int col);//判断胜利
void is_full(char board[ROW][COL], int row, int col);//判断是否填满,平局

 

 


http://www.niftyadmin.cn/n/4323.html

相关文章

java编程思想

文章目录 java编程思想第一章 对象导论面向对象语言OOP的五个特征每个对象都有一个接口每个对象都是提供服务的继承策略设计模式工厂方法设计模式泛型的引入并发,并行,多线程,关于共享资源的线程安全问题客户/服务器技术第二章 一切都是对象用引用操纵对象我们创建的对象存放…

深入理解 MyBatis 的核心配置

文章目录一、学习目标二、MyBatis 核心对象1.SqlSessionFactoryBuilder 对象2.SqlSessionFactory 对象3.SqlSession 对象三、MyBatis 核心配置文件1.核心配置文件中的主要元素2.properties 元素3.setting 元素4.typeAliases 元素5.environments 元素6.mappers 元素四、映射文件…

HALCON reference_hdevelop翻译Chapter1 1D Measuring(二)

以下是1D测量算子的详细解释,就只翻译重点内容了,基本的算子作用在上一篇文章都已经写出来了 close_measure 删除检测对象 close_measure删除被MeasureHandle创建的检测对象,被检测对象使用的内存就被释放了。 如果输入的参数没有问题,那么算子会返回值2 执行信息 多线…

OSPF高级配置——NSSA区域与地址汇总

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.NSSA区域 1. 非纯末梢 &#xff08;重点&#xff09; ① 链…

SubDAO与Moonbeam网络集成

跨链互连应用的最佳去中心化开发平台Moonbeam宣布与SubDAO集成&#xff0c;双方共享多链愿景和策略&#xff0c;因此此次集成对双方非常契合。现在&#xff0c;SubDAO已支持Moonbeam主网&#xff0c;允许Moonbeam用户轻松创建和管理DAO。 通过本次集成&#xff0c;用户可以创建…

C++ Reference: Standard C++ Library reference: C Library: cwchar: wcsncmp

C官网参考链接&#xff1a;https://cplusplus.com/reference/cwchar/wcsncmp/ 函数 <cwchar> wcsncmp int wcsncmp (const wchar_t* wcs1, const wchar_t* wcs2, size_t num); 比较两个宽字符串的字符 比较C宽字符串wcs1的最多num个字符与C宽字符串wcs2的字符。 这个函…

nginx配置之温故而知新

nginx是前端开发中使用的典型服务器&#xff0c;俗话说温故而知新&#xff0c;下面对nginx进行温故&#xff0c;看看能否知新。 一、HTTP服务器 nginx本身是一个静态资源的服务器&#xff0c;当只有静态资源的时候&#xff0c;就可以使用nginx来做服务器&#xff0c;如一个网站…

<Linux> 软件包管理器yum及编辑器vim的使用

文章目录一、yum的背景知识1. 商业生态2. 开源生态3. 软件生态本土化二、yum 的基本使用1. 查看软件包2. 安装、卸载、搜索软件实现Windows下和Linux下文件互传三、vim的基本使用1. vim 的基本概念2. vim 的基本操作2.1.模式间切换2.2.插入模式2.3.命令模式光标定位文本复制、粘…