linux贪吃蛇小程序,一个简单的贪吃蛇小程序

大部分都是根据马士兵老师的视频教程来编写的

1.[文件] Apple.java ~ 447B     下载(139)

package snake;

import java.awt.*;

import java.awt.event.*;

public class Apple {

int w = Yard.BLOCK_SIZE;

int h = Yard.BLOCK_SIZE;

int row, col;

Coordinate c = null;

Apple(Coordinate c) {

this.c = c;

this.row = c.y;

this.col = c.x;

}

void draw(Graphics g) {

Color c = g.getColor();

g.setColor(Color.YELLOW);

g.fillOval(col*w, row*h, w, h);

g.setColor(c);

}

}

2.[文件] Coordinate.java ~ 123B     下载(87)

package snake;

public class Coordinate {

int x, y;

Coordinate(int x, int y) {

this.x = x;

this.y = y;

}

}

3.[文件] Dir.java ~ 53B     下载(89)

package snake;

public enum Dir {

L, R, U, D

}

4.[文件] Snake.java ~ 5KB     下载(94)

package snake;

import java.awt.*;

import java.awt.event.*;

import java.util.*;

import snake.Coordinate;

import snake.Yard;

public class Snake {

int score;//用以计数

Node head = null;

Node tail = null;

Apple apples = null;

ArrayList coordinates = new ArrayList();//用来存放所有位置的坐标

//Yard yard = new Yard();QUESTION:StackOutError是怎么产生的?

Snake() {//初始化的蛇是一个有一头一尾向左运动的链表

Node head = new Node(Yard.ROWS/2, Yard.COLUMNS/2, Dir.L);

Node tail = new Node(Yard.ROWS/2+1, Yard.COLUMNS/2, Dir.L);

this.head = head;

this.tail = tail;

head.next = tail;

tail.last = head;

apples = new Apple(new Coordinate(10, 10));//蛇自带一个苹果

for(int y = 4; y <= Yard.ROWS - 2; y ++) {//QUESTION:有没有更加快捷的方法把所有元素添加进去呢?//将所有坐标都放入一个数组中

for(int x = 2; x <= Yard.COLUMNS - 2; x ++) {

coordinates.add(new Coordinate(x, y));

}

}

}

void addToTail() {

Node next = null;//ATTENTION:NULLPOINTEREXCEPTION!

switch(tail.dir) {

case L :

next = new Node(tail.row, tail.col+1, Dir.L);

break;

case R :

next = new Node(tail.row, tail.col-1, Dir.R);

break;

case U :

next = new Node(tail.row-1, tail.col, Dir.U);

break;

case D :

next = new Node(tail.row+1, tail.col, Dir.D);

break;

}

tail.next = next;//QUESTION:双向回环链表怎么搞?

next.last = tail;

tail = next;

}

void addToHead() {//QUSTION:这个方向还是有点不太清楚?

Node last = null;

switch(head.dir) {

case L :

last = new Node(head.row, head.col-1, Dir.L);

break;

case R :

last = new Node(head.row, head.col+1, Dir.R);

break;

case U :

last = new Node(head.row-1, head.col, Dir.U);

break;

case D :

last = new Node(head.row+1, head.col, Dir.D);

break;

}

head.last = last;

last.next = head;

head = last;

}

void deleteFromTail() {

tail = tail.last;

tail.next = null;

}

void deleteFromHead() {

head = head.next;

head.last = null;

}

void move() {

addToHead();

deleteFromTail();

if((head.row == apples.row && head.col == apples.col) == true) {//用以判定是否吃到苹果

score ++;

addToTail();

generate();

}

}

boolean dead() {//判断是否死亡

boolean smash = false;

for(Node n = head.next; n != tail; n = n.next) {//遍历除tail以外所有节点的位置,判断是否与head的坐标重合

if(head.coo.x == n.coo.x && head.coo.y == n.coo.y) {

smash = true;

}

}

if((head.coo.x < 2 || head.coo.x > Yard.COLUMNS - 2 ||//判断头部是否出界或者与其他节点坐标重合

head.coo.y < 4 || head.coo.y > Yard.ROWS - 2 || smash) == true)

return true;

else

return false;

}

void run() {

if(dead() == false)//如果确认死亡,停止移动

move();

}

void generate() {//用以产生新的apples

int num;

ArrayList s1 = new ArrayList();

ArrayList s2 = new ArrayList();

for(Node n = head; n != null; n=n.next) {

s1.add(n.coo);

}

s2 = coordinates;

s2.removeAll(s1);

num = (int)(s2.size()*Math.random());

apples = new Apple(s2.get(num));

}

public void keyPressed(KeyEvent e) {

int keyCode = e.getKeyCode();

switch(keyCode) {

case KeyEvent.VK_UP :

if(head.dir != Dir.D)

head.dir = Dir.U;

break;

case KeyEvent.VK_DOWN :

if(head.dir != Dir.U)

head.dir = Dir.D;

break;

case KeyEvent.VK_LEFT :

if(head.dir != Dir.R)

head.dir = Dir.L;

break;

case KeyEvent.VK_RIGHT :

if(head.dir != Dir.L)

head.dir = Dir.R;

break;

}

}

void draw(Graphics g) {

run();

for(Node n=head; n!=null; n=n.next) {

n.draw(g);

if(n == tail)//每次都将tail擦去可以有效地消除蛇的移动痕迹

n.erase(g);

}

if(dead() == true) {

g.setColor(Color.RED);

g.setFont(Font.getFont("Blackadder ITC"));

g.drawString("GAME OVER", 300, 300);

}

apples.draw(g);//之所以apples不用重画,是因为蛇吃到apples以后,tail的erase方法会顺带将apples擦除

}

private class Node {

int w = Yard.BLOCK_SIZE;

int h = Yard.BLOCK_SIZE;

int row, col;

Coordinate coo;

Dir dir = Dir.D;

Node next;//next和last可以将snake构成一个双向链表

Node last;

Node(int row, int col, Dir dir) {

this.row = row;

this.col = col;

this.dir = dir;

coo = new Coordinate(col, row);

}

void draw(Graphics g) {

Color c = g.getColor();

g.setColor(Color.BLACK);

g.fillRect(col*w, row*h, w, h);

g.setColor(c);

}

void erase(Graphics g) {

Color c = g.getColor();

g.setColor(Color.GRAY);

g.fillRect(col*w, row*h, w, h);

g.setColor(c);

}

}

}

5.[文件] Yard.java ~ 2KB     下载(93)

package snake;

import java.awt.*;

import java.awt.event.*;

public class Yard extends Frame {

static int X_0 = 200;

static int Y_0 = 0;

static int ROWS = 60;

static int COLUMNS = 60;

static int BLOCK_SIZE = 10;//QUESTION:只有静态变量才能被其他类使用?

Image offScreenImage = null;

Snake snake = new Snake();

public void launch() {//画出底层框架背景

this.addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent e) {

System.exit(0);//QUESTION:这里有必要先调用setvisible()吗?

}

});

this.addKeyListener(new KeyMonitor());

this.setBounds(X_0, Y_0, ROWS*BLOCK_SIZE, COLUMNS*BLOCK_SIZE);//

this.setBackground(Color.GRAY);

this.setTitle("Snake");

this.setVisible(true);

new Thread(new PaintThread()).start();//作为子进程来运行,能够让背景不用多次重画

}

public void paint(Graphics g) {

//super.paint(g);QUESTION:有什么用?

snake.draw(g);//QUESTION:这个擦除问题还是不好解决//先画蛇,使蛇在最底层运动

g.setColor(Color.GRAY);//擦除重叠的分数,以保证显示清晰。

g.fillRect(60, 50, 10, 10);

Color c = g.getColor();

g.setColor(Color.BLACK);

for(int i=0; i

g.drawLine(i*BLOCK_SIZE, 0, i*BLOCK_SIZE, COLUMNS*BLOCK_SIZE);

}

g.setColor(Color.BLACK);

for(int i=0; i

g.drawLine(0, i*BLOCK_SIZE, ROWS*BLOCK_SIZE, i*BLOCK_SIZE);

}

g.setColor(Color.WHITE);//用以显示分数,

g.drawString("Score:" + snake.score, 30, 60);

g.setColor(c);

}

public void update(Graphics g) {//QUESTION:双缓冲如何实现?

if(offScreenImage == null) {//QUESTION:哪里来的NULLPOINTEREXCEPTION?

offScreenImage = this.createImage(ROWS*BLOCK_SIZE, COLUMNS*BLOCK_SIZE);

}

Graphics gOff = offScreenImage.getGraphics();

paint(gOff);

g.drawImage(offScreenImage, 0, 0, null);

}

public static void main(String[] args) {

new Yard().launch();

}

private class PaintThread implements Runnable {

public void run() {//QUESTION:private类里的public方法的访问权限是怎么样的呢?

while(true) {

repaint();

try {

Thread.sleep(100);//ATTENTION!

} catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}

private class KeyMonitor extends KeyAdapter {

public void keyPressed(KeyEvent e) {

snake.keyPressed(e);

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单贪吃蛇游戏服务器的代码实现,仅供参考: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT 8888 #define MAX_CLIENTS 10 #define BUFFER_SIZE 1024 typedef struct { int x; int y; } point; typedef struct { int id; int score; point pos[100]; int len; } snake; snake snakes[MAX_CLIENTS]; int num_clients = 0; int main(int argc, char *argv[]) { int server_fd, client_fds[MAX_CLIENTS]; struct sockaddr_in server_addr, client_addr; char buffer[BUFFER_SIZE]; int i, j, k, n; int max_fd, fd; fd_set read_fds; socklen_t client_len = sizeof(client_addr); // 初始化蛇的状态 for (i = 0; i < MAX_CLIENTS; i++) { snakes[i].id = i + 1; snakes[i].score = 0; snakes[i].len = 3; for (j = 0; j < snakes[i].len; j++) { snakes[i].pos[j].x = j + 1; snakes[i].pos[j].y = 1; } } // 创建服务器套接字 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } // 绑定服务器地址 memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(PORT); if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { perror("bind"); exit(1); } // 监听客户端连接 if (listen(server_fd, MAX_CLIENTS) == -1) { perror("listen"); exit(1); } // 循环处理客户端请求 while (1) { // 初始化文件描述符集合 FD_ZERO(&read_fds); FD_SET(server_fd, &read_fds); max_fd = server_fd; for (i = 0; i < num_clients; i++) { FD_SET(client_fds[i], &read_fds); if (client_fds[i] > max_fd) { max_fd = client_fds[i]; } } // 等待事件发生 if (select(max_fd + 1, &read_fds, NULL, NULL, NULL) == -1) { perror("select"); exit(1); } // 处理服务器套接字有新连接 if (FD_ISSET(server_fd, &read_fds)) { if ((client_fds[num_clients] = accept(server_fd, (struct sockaddr *)&client_addr, &client_len)) == -1) { perror("accept"); continue; } printf("New client connected: %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); num_clients++; } // 处理客户端有数据到达 for (i = 0; i < num_clients; i++) { if (FD_ISSET(client_fds[i], &read_fds)) { if ((n = read(client_fds[i], buffer, BUFFER_SIZE)) <= 0) { // 客户端断开连接 printf("Client disconnected: %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); close(client_fds[i]); for (j = i; j < num_clients - 1; j++) { client_fds[j] = client_fds[j + 1]; } num_clients--; continue; } // 处理客户端发送的消息 buffer[n] = '\0'; printf("Received message from client %d: %s\n", i + 1, buffer); // 更新蛇的位置 for (j = 0; j < MAX_CLIENTS; j++) { if (snakes[j].id == i + 1) { for (k = snakes[j].len - 1; k > 0; k--) { snakes[j].pos[k].x = snakes[j].pos[k - 1].x; snakes[j].pos[k].y = snakes[j].pos[k - 1].y; } if (buffer[0] == 'U') { snakes[j].pos[0].y--; } else if (buffer[0] == 'D') { snakes[j].pos[0].y++; } else if (buffer[0] == 'L') { snakes[j].pos[0].x--; } else if (buffer[0] == 'R') { snakes[j].pos[0].x++; } break; } } // 发送蛇的状态给所有客户端 for (j = 0; j < num_clients; j++) { memset(buffer, 0, BUFFER_SIZE); for (k = 0; k < MAX_CLIENTS; k++) { if (snakes[k].id == j + 1) { sprintf(buffer + strlen(buffer), "%d,%d,%d;", snakes[k].id, snakes[k].score, snakes[k].len); for (n = 0; n < snakes[k].len; n++) { sprintf(buffer + strlen(buffer), "%d,%d;", snakes[k].pos[n].x, snakes[k].pos[n].y); } break; } } write(client_fds[j], buffer, strlen(buffer)); } } } } return 0; } ``` 主要思路是:创建一个服务器套接字,监听客户端连接。当有新客户端连接时,将其加入到文件描述符集合中,并为其创建一个蛇的状态。当客户端发送消息时,更新相应的蛇的位置,并将所有蛇的状态发送给所有客户端。当客户端断开连接时,将其从文件描述符集合中移除,并将其对应的蛇的状态从服务器中删除。 这个程序只是一个简单的示例,可能还需要进行一些改进和优化,比如处理客户端之间的碰撞、吃食物等逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值