1. 程式人生 > >C語言遊戲之貪吃蛇--連結串列實現

C語言遊戲之貪吃蛇--連結串列實現

早自習時突然想到怎麼寫貪吃蛇,話不多說,程式碼如下:

開發環境:vs2015

雖然開始還是出了很多指標問題。。。(很煩C語言指標)除錯了很久也大概是可以暢快的玩了。

C語言新手,有很多寫得不好的地方望大神提出

當然,我也不介意把我程式碼拿去學習(這樣就說明我的程式碼有學習價值偷笑

標頭檔案:snake.h

/**
*By Liu Yuchuan
*2017.3.30
*/

#ifndef SNAKE_H_INCLUDED
#define SNAKE_H_INCLUDED
#include<stdio.h>

//遊戲中各種符號
#define CHOOSE_LOGO "->"
#define SNAKE_NODE '*'
#define WALL '#'
#define FOOD '$'

//地圖大小
#define mapWidth 50
#define mapHeight 25

//蛇狀態
#define LIVE 1
#define DEAD 0

//移動方向
enum Direction{UP, DOWN, RIGHT, LEFT};
typedef enum Direction Direction;

struct Node;
typedef struct Node  Node;
typedef Node* SnakeHead;
typedef Node* PtrToNode;

//蛇的連結串列節點
struct Node{
	int x;
	int y;
	PtrToNode next;
};


//蛇的結構體
typedef struct Snake{
	SnakeHead snakeHead;
	int lenth;
	int state;
	Direction dir;
} *Snake;

//食物的結構體
typedef struct Food {
	int x;
	int y;
	int isEat;
} *Food;

//移動鍵
char key_down = 's';
char key_up = 'w';
char key_right = 'd';
char key_left = 'a';

//移動間隔時間
int moveTime = 100;

//得分
int score = 0;

Food food = NULL;
Snake snake = NULL;

void menu();
void pos(int x, int y);
void startGame();
void initMap();
Snake initSnake(Snake snake);
void printSnake(Snake snake);
void clearSnake(Snake snake);
void move(Snake snake);
Snake getLonger(Snake snake);
void createFood();
int isLocationOK(int x, int y);

#endif // SNAKE_H_INCLUDED

原始碼:Snake.c

#include"Snake.h"
#include<windows.h>
#include<stdlib.h>
#include<conio.h>
#include<time.h>

int main(){
	menu:menu();
	system("cls");
	startGame();
	goto menu;
}

void menu(){
	pos(18, 2);
	printf("歡迎來到貪吃蛇!");

	//列印選單
	pos(18, 6);
	printf("%s", CHOOSE_LOGO);
	printf("開始遊戲");
	pos(20, 10);
	printf("退出遊戲");

	//控制選單
	int option = 0;
	char ch = 1;

	//鍵入回車退出迴圈
	while(1){
		ch = _getch();

		//下移
		if(ch == key_down){
			if(option == 0){
				pos(18, 6+option);
				printf("  ");
				option += 4;
				pos(18, 6+option);
				printf("%s", CHOOSE_LOGO);
			}
		}

		//上移
		else if(ch == key_up){
			if(option == 4){
				pos(18, 6+option);
				printf("  ");
				option -= 4;
				pos(18, 6+option);
				printf("%s", CHOOSE_LOGO);
			}
		}

		else if(ch == 13){
			switch(option){
				case 0:
					return;
				case 4:
					exit(0);
			}
		}
	}
}

//定位游標
void pos(int x, int y){
	COORD position;
	position.X = x;
	position.Y = y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), position);
}

void startGame(){
	char ch = 1;
	score = 0;
	snake = initSnake(snake);
	initMap();
	food = (Food)malloc(sizeof(struct Food));
	food->x = 0;
	food->y = 0;
	food->isEat = 1;
	printSnake(snake);
	while (snake->state){
		createFood(food);
		//監聽鍵盤輸入
		if (_kbhit()) {
			ch = _getch();
			if (snake->dir != UP && ch == key_down) {
				snake->dir = DOWN;
			}
			else if (snake->dir != DOWN && ch == key_up) {
				snake->dir = UP;
			}
			else if (snake->dir != LEFT && ch == key_right) {
				snake->dir = RIGHT;
			}
			else if (snake->dir != RIGHT && ch == key_left) {
				snake->dir = LEFT;
			}
		}

		move(snake);
	}

	pos(mapWidth + 2, mapHeight / 2 - 1);
	printf("                                       ");
	pos(mapWidth + 2, mapHeight / 2);
	printf("                                       ");
	pos(mapWidth + 2, mapHeight / 2 + 1);
	printf("                                       ");
	pos(mapWidth + 2, mapHeight / 2 + 2);
	printf("                                       ");
	pos(mapWidth + 2, mapHeight / 2 - 1);
	printf("遊戲結束");
	pos(mapWidth + 2, mapHeight / 2);
	printf("最終長度: %d", snake->lenth);
	pos(mapWidth + 2, mapHeight / 2 + 1);
	printf("您的得分: %d", score);
	pos(mapWidth + 2, mapHeight / 2 + 2);
	printf("Enter鍵返回主選單");

	while(ch != 13)
		ch = _getch();
	system("cls");
}

void initMap(){
	for(int i = 0; i < mapWidth; i++){
		for(int j = 0; j < mapHeight; j++){
			if(i == 0 || j == 0 || i == mapWidth - 1 || j == mapHeight - 1){
				pos(i, j);
				printf("%c", WALL);
			}
		}
	}

	pos(mapWidth + 2, mapHeight/2 - 1);
	printf("當前長度(越長吃一次食物得分越高哦):");
	pos(mapWidth + 2, mapHeight/2);
	printf("%d", snake->lenth);
	pos(mapWidth + 2, mapHeight / 2 + 1);
	printf("當前得分:");
	pos(mapWidth + 2, mapHeight / 2+2);
	printf("%d", score);
}

Snake initSnake(Snake snake){
	snake = (Snake)malloc(sizeof(struct Snake));
	snake->snakeHead = (SnakeHead)malloc(sizeof(Node));
	SnakeHead snakeHead = snake->snakeHead;
	snakeHead->x = 4;
	snakeHead->y = 3;
	snakeHead->next = (PtrToNode)malloc(sizeof(Node));
	snakeHead->next->x = 4;
	snakeHead->next->y = 2;
	snakeHead->next->next = (PtrToNode)malloc(sizeof(Node));
	snakeHead->next->next->x = 4;
	snakeHead->next->next->y = 1;
	snakeHead->next->next->next = NULL;
	snake->lenth = 3;
	snake->dir = DOWN;
	snake->state = LIVE;
	return snake;
}

void printSnake(Snake snake) {
	PtrToNode position = snake->snakeHead;
	while (position) {
		pos(position->x, position->y);
		printf("%c", SNAKE_NODE);
		position = position->next;
	}
}

void clearSnake(Snake snake){
	PtrToNode position = snake->snakeHead;
	while (position) {
		pos(position->x, position->y);
		printf(" ");
		position = position->next;
	}
}

void move(Snake snake) {

	//判斷是否會撞牆
	if ((snake->snakeHead->x == mapWidth - 2 && snake->dir == RIGHT)
		|| snake->snakeHead->x == 1 && snake->dir == LEFT
		|| snake->snakeHead->y == 1 && snake->dir == UP
		|| snake->snakeHead->y == mapHeight - 2 && snake->dir == DOWN) {
		snake->state = DEAD;
		return;
	}

	clearSnake(snake);
	SnakeHead head = snake->snakeHead;
	int x = head->x;
	int y = head->y;
	int tmpX, tmpY;
	switch (snake->dir) {
	case UP:
		head->y--;
		break;
	case DOWN:
		head->y++;
		break;
	case LEFT:
		head->x--;
		break;
	case RIGHT:
		head->x++;
		break;
	default:
		break;
	}

	while (head->next) {
		tmpX = head->next->x;
		tmpY = head->next->y;
		head->next->x = x;
		head->next->y = y;
		x = tmpX;
		y = tmpY;
		head = head->next;

		//判斷是否咬到自己
		if (head->x == snake->snakeHead->x
			&& head->y == snake->snakeHead->y)
			snake->state = DEAD;
	}

	if (snake->snakeHead->x == food->x
		&& snake->snakeHead->y == food->y && snake->state) {
		score += snake->lenth / 10 + 1;
		food->isEat = 1;
		pos(food->x, food->y);
		printf(" ");
		snake = getLonger(snake);
		pos(mapWidth + 2, mapHeight / 2 + 2);
		printf("%d", score);
		pos(mapWidth + 2, mapHeight / 2 );
		printf("%d", snake->lenth);
	}

	printSnake(snake);
	Sleep(moveTime);
}

Snake getLonger(Snake snake){
	PtrToNode position = snake->snakeHead;
	while (position->next->next) {
		position = position->next;
	}
	int x1 = position->x;
	int y1 = position->y;
	position = position->next;
	int x2 = position->x;
	int y2 = position->y;
	position->next = (PtrToNode)malloc(sizeof(Node));
	position->next->next = NULL;
	if (x1 == x2) {
		position->next->x = x1;
		position->next->y = y2 + y2 - y1;
	}
	else{
		position->next->y = y1;
		position->next->x = x2 + x2 - x1;
	}

	snake->lenth++;

	return snake;
}

//生成食物
void createFood(){
	if (food->isEat) {

		//獲取系統時間作為產生隨機數的種子
		srand((unsigned)time(0));
		while (1) {
			food->x = rand() % (mapWidth - 2) + 1;
			food->y = rand() % (mapHeight - 2) + 1;
			if (isLocationOK(food->x, food->y)) {
				pos(food->x, food->y);
				printf("%c", FOOD);
				food->isEat = 0;
				break;
			}
		}
	}
}

//判斷位置是否合理
int isLocationOK(int x, int y){
	PtrToNode position = snake->snakeHead;

	while (position) {
		if (x == position->x && y == position->y) {
			position = position->next;
			return 0;
		}
	}

	return x > 0 && x < mapWidth - 1
		&& y > 0 && y < mapHeight - 1;
}


相關推薦

C語言遊戲貪吃--連結串列實現

早自習時突然想到怎麼寫貪吃蛇,話不多說,程式碼如下: 開發環境:vs2015 雖然開始還是出了很多指標問題。。。(很煩C語言指標)除錯了很久也大概是可以暢快的玩了。 C語言新手,有很多寫得不好的地方望大神提出 當然,我也不介意把我程式碼拿去學習(這樣就說明我的程式碼有

字元介面的貪吃--連結串列--C++

前天看了下連結串列,由於平時對連結串列的使用不多,所以對連結串列的應用也沒什麼瞭解,所以想來想去,就想用連結串列實現一下貪吃蛇。 下面言歸正傳,先看效果圖,再看程式碼,其他沒有了! 圖1: 圖2: 程式碼: #include<iostream.h> //

C語言控制臺貪吃2

隨機數函數 edi mms ‘\0’ sign rand() 拷貝 printf rand 顯示遊戲邊框及蛇的位置初始化   一、顯示遊戲邊框    1、定義二位數組,例如20*48,將並邊框按行打印(運行顯示邊框會卡,暫時不會別的寫法QAQ) 註:一個方塊兩個字節。 /

C語言控制臺貪吃4

eba bsp console 食物 blog pan 是否 lec ons 蛇死亡判斷、吃食物、計分 一、蛇死亡判斷:裝邊界,撞自己死亡   定義:IsSnakeDie()//蛇死亡判斷 函數,返回類型為bool型 思路:   //蛇頭的下一個,是方塊 就是死亡

C語言寫的貪吃(國慶任務專案)

分享寫貪吃蛇的緣起 博主大一新生,因為有任務C語言寫貪吃蛇,去網上找別人的原始碼試一試效果,可是沒有一個可以通過編譯執行,現在博主好不容易寫完了貪吃蛇,卻深感單初不易,現在分享一下原始碼,應該不會像網上大多數的C語言貪吃蛇程式碼無法編譯正確,通過執行。(我用的D

c語言課上作業——初學連結串列操作

http://www.cnblogs.com/maluning/p/7966875.html 根據上面的大佬的指導。今天完成了老師的作業。第一次完成了連結串列的建立、遍歷、插入、刪除(基本靠抄,不好意思)。 作為一個菜鳥,第一次完成100行以上的不用複製重複程式碼的程式碼。好興奮呀。 //不過還是有一點

C語言程式設計 細節總結(連結串列

12 連結串列 12.1 連結串列概述 1.採用動態儲存分配的一種重要資料結構,一個連結串列中儲存的是一批同類型的相關聯資料 2.動態分配時,每個結點之間可以不連續,結點之間的聯絡可以用指標實現,每個結點分兩個域:資料域和指標域 12.2 處理動態連結串列所需函

leetcode C語言版 第142. 環形連結串列 II

給定一個連結串列,返回連結串列開始入環的第一個節點。 如果連結串列無環,則返回 null。說明:不允許修改給定的連結串列。進階:你是否可以不用額外空間解決此題?分析:我最開始想的是通過修改value值來判斷是否相遇,後來看見題目規定不能修改,遂涼涼。用快慢指標解答,至於為什麼

資料結構程式碼實現佇列的連結串列實現C/C++)

上班閒著無聊,一直想著要開始寫部落格,但又不知道寫什麼。最近又回顧了下資料結構的知識,那就從資料結構開始吧。 前言 關於C語言結構體的知識以及佇列的特性請讀者自行了解,此處不做過多解釋,嘻嘻。 同時此篇文章僅僅是關於佇列的連結串列實現。 第一步:結構體編寫 我們首先分析一下佇列的

C語言檔案讀取並寫入連結串列

C語言沒啥要逼逼的,直接上程式碼,用心體會 #include "stdio.h" #include "stdlib.h" /***************************** 連結串列節點結構體 ****************************/ typedef stru

C語言資料結構_Linux核心連結串列

C語言資料結構中,可以分為線性資料結構和非線性資料結構,其中線性資料結構非常重要的內容是連結串列,本文章從基本的連結串列過渡到Linux核心連結串列 資料與邏輯結合的連結串列   什麼是資料與邏輯結合?先回想曾經學過的各種連結串列:   

面向物件Python的連結串列實現(二)迴圈連結串列

接上一章的練習,這裡接著實現單鏈表的變型——傳說中的迴圈單鏈表。給出一個簡單的類,構造4個功能並例項化測試。 在下一篇文章中將會關注一個比較tricky的問題:如何判斷連結串列有環?以及求出環長度 # -*- coding: utf-8 -*- """ Created

C語言貪吃(詳解)——連結串列實現

貪吃蛇設計思路:螢幕座標:拓展功能:1.F1,F2控制加速減速  空格暫停遊戲  Esc退出2.加速每個食物得分更高先打印出遊戲介面,還有初始化蛇,蛇的節點用字串★表示,遊戲背景用■表示,因為這些字串佔兩個位元組的寬度,所以每次x,y座標的對應關係是x=y*2。在相應位置打印

C++控制檯迴圈連結串列實現貪吃

-stdafx.h 為了簡化程式定義一些巨集和全域性變數 #ifndef __STDAFX_H__ #define __STDAFX_H__ // ============上下左右=========

C語言資料結構靜態連結串列實現(A-B)U(B-A)

時間複雜度O(3n)不是很難,直接貼程式碼:StaticLinkList.h#ifndef _STATIC_LINK_LIST_H_ #define _STATIC_LINK_LIST_H_ #define MAXSIZE 100 typedef enum {ERROR,OK

C語言---經典雙向連結串列實現

int dlist_ins_next(Dlist *list, DListElement *element, const void *data){    DListElement *new_element;    if (element == NULL && list->size !=

資料結構與演算法分析c語言描述(Mark Allen)--佇列ADT連結串列實現

佇列ADT連結串列實現 使用連結串列儲存 操作集合 入隊 出隊 初始化 返回隊前元素 列印 #include <stdio.h> #includ

使用C語言連結串列實現商品管理系統

#include <stdio.h> #include <stdlib.h> #include <windows.h> #define bool char #define true 1 #define false 0 #define NUM 1

Leetcode中級演算法奇偶連結串列(328)C++

給定一個單鏈表,把所有的奇數節點和偶數節點分別排在一起。請注意,這裡的奇數節點和偶數節點指的是節點編號的奇偶性,而不是節點的值的奇偶性。 請嘗試使用原地演算法完成。你的演算法的空間複雜度應為 O(1),時間複雜度應為 O(nodes),nodes 為節點總數。 示例 1: 輸入:

C#LeetCode刷題#203-刪除連結串列中的節點(Remove Linked List Elements)

問題 刪除連結串列中等於給定值 val 的所有節點。 輸入: 1->2->6->3->4->5->6, val = 6 輸出: 1->2->3-&