c# console snake game

posted in phil67rpg's Blog
Published February 11, 2019
Advertisement

I have decided to work on a console based snake game, I am doing this because I want to learn basic c# skills before move on to c#  graphics programming.

I am able to move the snake from the center to the edge of the screen, it is just a start, but I am learning.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace snakegame
{
    class Program
    {
        static void Main(string[] args)
        {
            const int board_size = 17;
            char[,] board = new char[board_size, board_size];
            int horizontal = 5, vertical = 8, count = 0;

            for (int i = 0; i < board_size; i++) 
            {
                for (int j = 0; j < board_size; j++) 
                {
                    board[i, j] = '.';
                }
            }

            void draw_board()
            {
                for (int i = 0; i < board_size; i++)
                {
                    for (int j = 0; j < board_size; j++)
                    {
                        Console.Write(board[i, j]);
                    }
                    Console.WriteLine();
                }
            }

            while (count < 6)
            {
                board[vertical, horizontal] = '*';
                board[vertical, horizontal + 1] = '*';
                board[vertical, horizontal + 2] = '*';
                board[vertical, horizontal + 3] = '*';
                board[vertical, horizontal + 4] = '*';
                board[vertical, horizontal + 5] = '*';
                board[vertical, horizontal + 6] = '*';

                draw_board();

                horizontal++;
                count++;

                System.Threading.Thread.Sleep(1000);
                Console.Clear();
            }
        }
    }
}

 

Previous Entry c# snake game
1 likes 48 comments

Comments

8Observer8

I think it is better to use Timer instead of Sleep. I found this example in the Internet:


using System;
using System.Threading;

namespace Snake_ASCIICSharp
{
    class Program
    {
        public static void Main()
        {
            // Create a Timer object that knows to call our TimerCallback
            // method once every 2000 milliseconds.
            Timer t = new Timer(TimerCallback, null, 0, 2000);
            // Wait for the user to hit <Enter>
            Console.ReadLine();
        }

        private static void TimerCallback(Object o)
        {
            // Display the date/time when this method got called.
            Console.WriteLine("In TimerCallback: " + DateTime.Now);
            // Force a garbage collection to occur for this demo.
            GC.Collect();
        }
    }
}

 

February 11, 2019 12:27 PM
phil67rpg

here is my updated code


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace snakegame
{
    class Program
    {
        static void Main(string[] args)
        {
            const int board_size = 17;
            char[,] board = new char[board_size, board_size];
            int horizontal = 5, vertical = 8, count = 0;

            for (int i = 0; i < board_size; i++) 
            {
                for (int j = 0; j < board_size; j++) 
                {
                    board[i, j] = '.';
                }
            }

            void draw_board()
            {
                for (int i = 0; i < board_size; i++)
                {
                    for (int j = 0; j < board_size; j++)
                    {
                        Console.Write(board[i, j]);
                    }
                    Console.WriteLine();
                }
            }

            while (count < 6)
            {
                board[vertical, horizontal] = '*';
                board[vertical, horizontal + 1] = '*';
                board[vertical, horizontal + 2] = '*';
                board[vertical, horizontal + 3] = '*';
                board[vertical, horizontal + 4] = '*';
                board[vertical, horizontal + 5] = '*';
                board[vertical, horizontal + 6] = '*';

                draw_board();

                horizontal++;
                count++;

                System.Threading.Thread.Sleep(1000);
                Console.Clear();
            }
        }
    }
}

 

February 13, 2019 12:20 AM
CrazyCdn

Your updated source code is identical to your previous code, like literally line for line, character for character.

February 13, 2019 04:37 AM
Rutin
4 hours ago, CrazyCdn said:

Your updated source code is identical to your previous code, like literally line for line, character for character.

https://www.diffchecker.com/EdxR7ubb

?

I had a bit of a chuckle.

February 13, 2019 08:41 AM
8Observer8

Please, when you publish your code select this option in right-bottom corner of forum code editor:

30093068_CLanguages.png.2467cb0d06f71fa9ca305083d02ad122.png

February 13, 2019 10:45 AM
CrazyCdn
8 hours ago, Rutin said:

https://www.diffchecker.com/EdxR7ubb

?

I had a bit of a chuckle.

I did the exact same thing.  I swear he is a long term troll of gamedev.  People keep trying to help him, like @8Observer8, but he will say he understands what they're saying then post code a short bit later with none of the changes.  For a good laugh I've scrolled through his post history before, man I wish I had made popcorn.

February 13, 2019 05:32 PM
phil67rpg

crazycdn I am sorry I posted identical code everbody makes mistakes, thanks for all the input

This is my real updated code.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace snakegame
{
    class Program
    {
        static void Main(string[] args)
        {
            const int board_size = 17;
            char[,] board = new char[board_size, board_size];
            int horizontal = 5, vertical = 8, count = 0;

            for (int i = 0; i < board_size; i++) 
            {
                for (int j = 0; j < board_size; j++) 
                {
                    board[i, j] = '.';
                }
            }

            void draw_board()
            {
                for (int i = 0; i < board_size; i++)
                {
                    for (int j = 0; j < board_size; j++)
                    {
                        Console.Write(board[i, j]);
                    }
                    Console.WriteLine();
                }
            }

            while (count < 12)
            {
                if (count >= 0 && count < 6)
                {
                    board[vertical, horizontal] = '*';
                    board[vertical, horizontal + 1] = '*';
                    board[vertical, horizontal + 2] = '*';
                    board[vertical, horizontal + 3] = '*';
                    board[vertical, horizontal + 4] = '*';
                    board[vertical, horizontal + 5] = '*';
                    board[vertical, horizontal + 6] = '*';

                    draw_board();

                    horizontal++;
                }

                if (count > 5 && count < 12)
                {
                    board[vertical, horizontal] = '*';
                    board[vertical+1, horizontal] = '*';
                    board[vertical+2, horizontal] = '*';
                    board[vertical+3, horizontal] = '*';
                    board[vertical+4, horizontal] = '*';
                    board[vertical+5, horizontal] = '*';
                    board[vertical+6, horizontal] = '*';

                    draw_board();

                    vertical++;
                }

                count++;

                System.Threading.Thread.Sleep(1000);
                Console.Clear();
            }
        }
    }
}

 

February 13, 2019 06:48 PM
unbird
2 hours ago, CrazyCdn said:

... I swear he is a long term troll of gamedev...

Or the most successful Turing test to date.

February 13, 2019 07:35 PM
Awoken
1 hour ago, unbird said:

Or the most successful Turing test to date.

I actually had thought this too...  lol

I think phil is my hero.  

February 13, 2019 08:38 PM
8Observer8

My opinion that it is more difficult to use Console for the Snake Game. It is more simple to use WinForms Graphics class or graphics from WPF. Try to improve my example 101. Snake. WinForms, GDI+ Add lives, "game over", scores, sounds, music and so on. I like irrKlang library for music/sounds because it is more simple that OpenAL. Work hard and you will see your progress. Motivate yourself and have fun.

February 14, 2019 07:22 PM
phil67rpg

well I have decided to take observers advice and work on a winform gdi+ snake game. I am able to make the snake head to move to the  right in the screen. here is my code so far, I am just starting on my project.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {

        }

        int x = 0, y = 0;

        private void timer1_Tick(object sender, EventArgs e)
        {
            Graphics g = this.CreateGraphics();
            SolidBrush greenBrush = new SolidBrush(Color.Green);
            SolidBrush blackBrush = new SolidBrush(Color.Black);
            Rectangle rect_green = new Rectangle(340 + x, 280 + y, 10, 10);
            Rectangle rect_black = new Rectangle(330 + x, 280 + y, 10, 10);
            g.FillRectangle(greenBrush, rect_green);
            g.FillRectangle(blackBrush, rect_black);
            if (x >= 340)
            {
                x = 340;
            }
            x += 5;
            greenBrush.Dispose();
            g.Dispose();

            if (MouseButtons == MouseButtons.Left)
            {

            }
        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {

        }
    }
}

 

February 16, 2019 02:05 AM
duke_meister

I don't think there's a problem using the console. I think it's an interesting challenge. Plus also haven't you already written the GDI one? :)

ed: ok after a quick look, it doesn't seem that much fun. It's just too slow without some advanced console IO.

February 16, 2019 09:04 AM
8Observer8
8 hours ago, phil67rpg said:

I am able to make the snake head to move to the  right in the screen. here is my code so far, I am just starting on my project.

I ran your project but I do not see the snake head which moves to the right.

I see three problems in your code:

  1. You need to call drawing from the Form1_Paint() method
  2. You do not call the Invalidate() method in the timer1_Tick() method
  3. You have too big offset for the snake head:

Rectangle rect_green = new Rectangle(340 + x, 280 + y, 10, 10);
Rectangle rect_black = new Rectangle(330 + x, 280 + y, 10, 10);

Default size of windows is 300x300.

I solved these problems:

SnakeByPhil_WinFormsGDI.gif.60990c5722280d7fc5e0481df90f5ef5.gif


using System;
using System.Drawing;
using System.Windows.Forms;

namespace SnakeByPhil_WinFormsGDI
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            CenterToScreen();
        }

        int x = 0, y = 0;

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = this.CreateGraphics();
            SolidBrush greenBrush = new SolidBrush(Color.Green);
            SolidBrush blackBrush = new SolidBrush(Color.Black);
            Rectangle rect_green = new Rectangle(20 + x, 20 + y, 10, 10);
            Rectangle rect_black = new Rectangle(10 + x, 20 + y, 10, 10);
            g.FillRectangle(greenBrush, rect_green);
            g.FillRectangle(blackBrush, rect_black);
            greenBrush.Dispose();
            g.Dispose();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (x >= 340)
            {
                x = 340;
            }
            x += 5;

            if (MouseButtons == MouseButtons.Left)
            {

            }
            Invalidate();
        }
    }
}

 

February 16, 2019 09:57 AM
phil67rpg

well duke thanks for the code but I cant learn by copying someone else code. let me work on what observer  has sent me. I can only digest so much code at one time.

February 16, 2019 07:34 PM
duke_meister

You said you'd changed your mind from doing console, so I went for it :) 

Take a piece and analyse it. I'm happy to go over each aspect one at a time. Want me to do that? If so I'll add comments in the code.

Much of it is relevant to your GDI project.

February 16, 2019 09:57 PM
phil67rpg

thanks duke I am doing the graphics c# because observer said it is easier. I am able to get the snake to move up and down and left and right but I want it to move smoother animation.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = this.CreateGraphics();
            SolidBrush greenBrush = new SolidBrush(Color.Green);
            SolidBrush blackBrush = new SolidBrush(Color.Black);
            Rectangle rect_green = new Rectangle(340 + x, 280 + y, 10, 10);
            Rectangle rect_black = new Rectangle(330 + x, 280 + y, 10, 10);
            g.FillRectangle(greenBrush, rect_green);
            g.FillRectangle(blackBrush, rect_black);
            greenBrush.Dispose();
            g.Dispose();
        }

        int x = 0, y = 0;

        Random rnd = new Random();

        private void timer1_Tick(object sender, EventArgs e)
        {
            int move = rnd.Next(1, 5);

            switch (move)
            {
                case 1:
                    for (int i = 0; i <= 20; i++)
                    {
                        x++;
                    }
                    break;
                case 2:
                    for (int i = 0; i <= 20; i++)
                    {
                        x--;
                    }
                    break;
                case 3:
                    for (int i = 0; i <= 20; i++)
                    {
                        y++;
                    }
                    break;
                case 4:
                    for (int i = 0; i <= 20; i++)
                    {
                        y--;
                    }
                    break;
            }

            if (MouseButtons == MouseButtons.Left)
            {

            }
            Invalidate();
        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {

        }
    }
}

 

February 16, 2019 10:08 PM
duke_meister

No problem. I've created a blog for it, so as not to confuse yours. See some updated code there.

As for 'easier'.... that's a subjective concept :)

February 17, 2019 12:59 AM
phil67rpg

well I am making a graphics c# program. can you give me just a hint as how to make the snake smooth animation.

February 17, 2019 02:17 AM
duke_meister
8 hours ago, phil67rpg said:

well I am making a graphics c# program. can you give me just a hint as how to make the snake smooth animation.

There's not enough there yet to comment on.

Idea: have a look at the structure of the game on my blog. Maybe an exercise would be to take that structure and turn it into a GDI version. I could help with that.

Or if you're interested in learning gradually, I could start another blog and build the game up step by step?

By the way, a GDI snake game is more difficult in my opinion.

Anyway. Draw on a Panel. Make sure double buffering is set on the form/panel.

https://stackoverflow.com/questions/4305011/c-sharp-panel-for-drawing-graphics-and-scrolling?noredirect=1&amp;lq=1

 

BTW My blog is 

 

February 17, 2019 09:55 AM
8Observer8
2 hours ago, duke_meister said:

By the way, a GDI snake game is more difficult in my opinion.

I think "more difficult"... that's a subjective concept. For me making a ASCII snake game is more difficult than a snake game using: GDI/WinForms, OpenGL/OpenTK, WPF or Unity.

14 hours ago, phil67rpg said:

but I want it to move smoother animation.

I will add the smooth animation later. I think how to make it simpler. The classic game game does not have the smooth animation. But it is very interesting.

February 17, 2019 11:36 AM
8Observer8

I added timer2 which sets a new random direction every 500 milliseconds:

 

SnakeByPhil_RandomMovement.gif.623c5149affc52b28bd2560ccbf9898e.gif


using System;
using System.Drawing;
using System.Windows.Forms;

namespace SnakeByPhil_WinFormsGDI
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            CenterToScreen();

            timer1.Interval = 200;

            timer2.Interval = 500;
            timer2.Start();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = this.CreateGraphics();
            SolidBrush greenBrush = new SolidBrush(Color.Green);
            SolidBrush blackBrush = new SolidBrush(Color.Black);
            //Rectangle rect_green = new Rectangle(340 + x, 280 + y, 10, 10);
            //Rectangle rect_black = new Rectangle(330 + x, 280 + y, 10, 10);
            Rectangle rect_green = new Rectangle(150 + x, 150 + y, 10, 10);
            Rectangle rect_black = new Rectangle(140 + x, 150 + y, 10, 10);
            g.FillRectangle(greenBrush, rect_green);
            g.FillRectangle(blackBrush, rect_black);
            greenBrush.Dispose();
            g.Dispose();
        }

        int x = 0, y = 0;

        Random rnd = new Random();

        int move = 1;

        private void timer2_Tick(object sender, EventArgs e)
        {
            move = rnd.Next(1, 5);
            Console.WriteLine(move);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            switch (move)
            {
                case 1:
                    for (int i = 0; i <= 20; i++)
                    {
                        x++;
                    }
                    break;
                case 2:
                    for (int i = 0; i <= 20; i++)
                    {
                        x--;
                    }
                    break;
                case 3:
                    for (int i = 0; i <= 20; i++)
                    {
                        y++;
                    }
                    break;
                case 4:
                    for (int i = 0; i <= 20; i++)
                    {
                        y--;
                    }
                    break;
            }

            if (MouseButtons == MouseButtons.Left)
            {

            }
            Invalidate();
        }
    }
}

 

February 17, 2019 12:04 PM
8Observer8

@phil67rpg do you have a plan to start learning of WPF instead of WinForms in the future? WinForms uses GDI (CPU - Central Processor Unit on central processor for rendering graphics) and it is very slowly than WPF because WPF use a graphics card on the hood (GPU - Graphics Processor Unit on graphics card for rendering graphics).

Do not afraid XAML. You can create graphics from C# code like in WinForms. XAML you can study later. XAML is like HTML. It is not difficult and it is more confiniant than WinForms. I think it is better do not spend time with WinForms. It is ideal to embed OpenTK.GLControl to use OpenGL 3 in you WinForms or WPF application. Or you can create GameWindow from Console Project using OpenTK. Studying WPF Graphics is good to because we have a great book about computer graphics that use WPF C#: 

February 17, 2019 12:23 PM
phil67rpg

I want to finish my project before I pursue WPF. I made some changes to my code.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            CenterToScreen();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = this.CreateGraphics();
            SolidBrush greenBrush = new SolidBrush(Color.Green);
            SolidBrush blackBrush = new SolidBrush(Color.Black);
            Rectangle rect_green = new Rectangle(340 + x, 280 + y, 10, 10);
            Rectangle rect_black = new Rectangle(330 + x, 280 + y, 10, 10);
            g.FillRectangle(greenBrush, rect_green);
            g.FillRectangle(blackBrush, rect_black);
            greenBrush.Dispose();
            g.Dispose();
        }

        int x = 0, y = 0;

        Random rnd = new Random();

        int move = 1;

        private void timer2_Tick(object sender, EventArgs e)
        {
            move = rnd.Next(1, 5);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            switch (move)
            {
                case 1:
                    for (int i = 0; i <= 20; i++)
                    {
                        if (x >= 440) 
                        {
                            x = 0;
                        }
                        x++;
                    }
                    break;
                case 2:
                    for (int i = 0; i <= 20; i++)
                    {
                        if (x <= -420) 
                        {
                            x = 0;
                        }
                        x--;
                    }
                    break;
                case 3:
                    for (int i = 0; i <= 20; i++)
                    {
                        if (y >= 280) 
                        {
                            y = 0;
                        }
                        y++;
                    }
                    break;
                case 4:
                    for (int i = 0; i <= 20; i++)
                    {
                        if (y <= -280)
                        {
                            y = 0;
                        }
                        y--;
                    }
                    break;
            }

            if (MouseButtons == MouseButtons.Left)
            {

            }
            Invalidate();
        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {

        }
    }
}

 

February 17, 2019 10:41 PM
duke_meister
12 hours ago, 8Observer8 said:
14 hours ago, duke_meister said:

By the way, a GDI snake game is more difficult in my opinion.

I think "more difficult"... that's a subjective concept

Yes that's what I said in a previous post, so we agree.

February 18, 2019 12:03 AM
phil67rpg

I want to draw the food on the screen but what I get is the food is drawn randomly all over the screen.


        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = this.CreateGraphics();
            int food_x = rnd.Next(0, 770);
            int food_y = rnd.Next(0, 550);
            SolidBrush greenBrush = new SolidBrush(Color.Green);
            SolidBrush blackBrush = new SolidBrush(Color.Black);
            SolidBrush redBrush = new SolidBrush(Color.Red);
            Rectangle rect_green = new Rectangle(340 + x, 280 + y, 10, 10);
            Rectangle rect_black = new Rectangle(330 + x, 280 + y, 10, 10);
            Rectangle rect_red = new Rectangle(food_x , food_y , 10, 10);
            g.FillRectangle(greenBrush, rect_green);
            g.FillRectangle(blackBrush, rect_black);
            g.FillRectangle(redBrush, rect_red);
            redBrush.Dispose();
            blackBrush.Dispose();
            greenBrush.Dispose();
            g.Dispose();
        }

 

February 18, 2019 03:03 AM
CrazyCdn
1 hour ago, phil67rpg said:

I want to draw the food on the screen but what I get is the food is drawn randomly all over the screen.

Because you're randomly drawing it all over the screen... Well technically in the ranges of 330 - 340 + 0 - 770 and 280 + 0 - 550.  What were you expecting random to do?  Don't call the randomize function Form1_Paint() each frame and you won't get a new food items each frame.

February 18, 2019 05:00 AM
duke_meister

Paint gets called all the time. And you randomize the placement. That's why you get many all over the place.

Also use e.Graphics

February 18, 2019 06:02 AM
8Observer8
10 hours ago, phil67rpg said:

I want to draw the food on the screen but what I get is the food is drawn randomly all over the screen.



        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = this.CreateGraphics();
            int food_x = rnd.Next(0, 770);
            int food_y = rnd.Next(0, 550);
            SolidBrush greenBrush = new SolidBrush(Color.Green);
            SolidBrush blackBrush = new SolidBrush(Color.Black);
            SolidBrush redBrush = new SolidBrush(Color.Red);
            Rectangle rect_green = new Rectangle(340 + x, 280 + y, 10, 10);
            Rectangle rect_black = new Rectangle(330 + x, 280 + y, 10, 10);
            Rectangle rect_red = new Rectangle(food_x , food_y , 10, 10);
            g.FillRectangle(greenBrush, rect_green);
            g.FillRectangle(blackBrush, rect_black);
            g.FillRectangle(redBrush, rect_red);
            redBrush.Dispose();
            blackBrush.Dispose();
            greenBrush.Dispose();
            g.Dispose();
        }

 

Let's structure the code a little bit. I think it is more convenient to separate drawing and action. This code is just for example. The code below is bad because the snake changes a move direction with changing a food position. Could you explain how do you want to control the snake? By mouse click? Or the snake must move yourself with simple AI (path finding)?


        int food_x = 0;
        int food_y = 0;

        private void timer2_Tick(object sender, EventArgs e)
        {
            move = rnd.Next(1, 5);
            food_x = rnd.Next(0, 200);
            food_y = rnd.Next(0, 200);
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = this.CreateGraphics();
            SolidBrush greenBrush = new SolidBrush(Color.Green);
            SolidBrush blackBrush = new SolidBrush(Color.Black);
            SolidBrush redBrush = new SolidBrush(Color.Red);
            //Rectangle rect_green = new Rectangle(340 + x, 280 + y, 10, 10);
            //Rectangle rect_black = new Rectangle(330 + x, 280 + y, 10, 10);
            Rectangle rect_green = new Rectangle(150 + x, 150 + y, 10, 10);
            Rectangle rect_black = new Rectangle(140 + x, 150 + y, 10, 10);
            Rectangle rect_red = new Rectangle(food_x, food_y, 10, 10);
            g.FillRectangle(greenBrush, rect_green);
            g.FillRectangle(blackBrush, rect_black);
            g.FillRectangle(redBrush, rect_red);
            redBrush.Dispose();
            blackBrush.Dispose();
            greenBrush.Dispose();
            g.Dispose();
        }

 

February 18, 2019 12:03 PM
phil67rpg

observer your code still draws the  food all over the screen

February 18, 2019 06:38 PM
8Observer8

I do not understand where and when the food must be drawn. Please, explain me. It is better to write it in Paint. For example, you can generate next food when the snake eat one. Or do you want to generate food periodically? For example, every 5 seconds?

February 18, 2019 06:47 PM
phil67rpg

yeah!! observer I put the food in the form_load method and it works, thanks for all the input.

February 18, 2019 06:54 PM
8Observer8

@phil67rpg what do you think about this improving of your code?

Let's to rewrite this method:


        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = this.CreateGraphics();
            SolidBrush greenBrush = new SolidBrush(Color.Green);
            SolidBrush blackBrush = new SolidBrush(Color.Black);
            SolidBrush redBrush = new SolidBrush(Color.Red);
            Rectangle rect_green = new Rectangle(340 + x, 280 + y, 10, 10);
            Rectangle rect_black = new Rectangle(330 + x, 280 + y, 10, 10);
            Rectangle rect_red = new Rectangle(food_x, food_y, 10, 10);
            g.FillRectangle(greenBrush, rect_green);
            g.FillRectangle(blackBrush, rect_black);
            g.FillRectangle(redBrush, rect_red);
            redBrush.Dispose();
            blackBrush.Dispose();
            greenBrush.Dispose();
            g.Dispose();
        }

I think it looks better:


        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = this.CreateGraphics();
            DrawRectangle(g, 340 + x, 280 + y, Color.Green);
            DrawRectangle(g, 330 + x, 280 + y, Color.Black);
            DrawRectangle(g, food_x, food_y, Color.Red);
            g.Dispose();
        }

        private void DrawRectangle(Graphics g, int x, int y, Color color)
        {
            SolidBrush brush = new SolidBrush(color);
            Rectangle rect = new Rectangle(x, y, 10, 10);
            g.FillRectangle(brush, rect);
            brush.Dispose();
        }

 

February 18, 2019 07:11 PM
8Observer8

If you add DrawRactange() method then drawing food will be easier:


        struct Food { public int x; public int y; };

        List<Food> foods = new List<Food>() { new Food() };

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = this.CreateGraphics();
            DrawRectangle(g, 340 + x, 280 + y, Color.Green);
            DrawRectangle(g, 330 + x, 280 + y, Color.Black);

            foreach (var f in foods)
            {
                DrawRectangle(g, f.x, f.y, Color.Red);
            }

            g.Dispose();
        }

 

How it looks now:

SnakeByPhil_ListOfFood.gif.8863c0bdf92ab1637a75fec61e0ef281.gif


using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace SnakeByPhil_WinFormsGDI
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            CenterToScreen();

            timer1.Interval = 200;

            timer2.Interval = 500;
            timer2.Start();
        }

        int x = 0, y = 0;

        Random rnd = new Random();

        int move = 1;

        struct Food { public int x; public int y; };

        List<Food> foods = new List<Food>() { new Food() };

        private void timer2_Tick(object sender, EventArgs e)
        {
            move = rnd.Next(1, 5);
            int food_x = rnd.Next(0, 290);
            int food_y = rnd.Next(0, 290);
            foods.Add(new Food() { x = food_x, y = food_y });
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = this.CreateGraphics();
            DrawRectangle(g, 340 + x, 280 + y, Color.Green);
            DrawRectangle(g, 330 + x, 280 + y, Color.Black);

            foreach (var f in foods)
            {
                DrawRectangle(g, f.x, f.y, Color.Red);
            }

            g.Dispose();
        }

        private void DrawRectangle(Graphics g, int x, int y, Color color)
        {
            SolidBrush brush = new SolidBrush(color);
            Rectangle rect = new Rectangle(x, y, 10, 10);
            g.FillRectangle(brush, rect);
            brush.Dispose();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            switch (move)
            {
                case 1:
                    for (int i = 0; i <= 20; i++)
                    {
                        x++;
                    }
                    break;
                case 2:
                    for (int i = 0; i <= 20; i++)
                    {
                        x--;
                    }
                    break;
                case 3:
                    for (int i = 0; i <= 20; i++)
                    {
                        y++;
                    }
                    break;
                case 4:
                    for (int i = 0; i <= 20; i++)
                    {
                        y--;
                    }
                    break;
            }

            if (MouseButtons == MouseButtons.Left)
            {

            }
            Invalidate();
        }
    }
}

 

February 18, 2019 08:18 PM
duke_meister

Did you take anything from my console snake blog? At least see how you can structure your code.

Food doesn't have x,y values. A position (i.e. screen position) does though.


public class Pos
{
    public int X { get; set; }
    public int Y { get; set; }

    public Pos(int x, int y)
    {
        X = x;
        Y = y;
    }
}

Then you can have a position for your food (there is only one in my version of the game).


static Pos FoodPos = new Pos(0, 0);

As I already mentioned, don't create your own Graphics object. There's one for you in the Paint event.


e.Graphics

But I would first try the most basic thing, make a square move when the user presses an arrow key. That's it. No timers, randomized things, etc. Then move on.

February 19, 2019 09:25 AM
8Observer8
2 hours ago, duke_meister said:

No timers, randomized things, etc.

I think @phil67rpg wants to create a list of foods in random position. Or maybe I understand wrong. Okay, lets generate one food after eating.

2 hours ago, duke_meister said:

Food doesn't have x,y values. A position (i.e. screen position) does though.



public class Pos
{
    public int X { get; set; }
    public int Y { get; set; }

    public Pos(int x, int y)
    {
        X = x;
        Y = y;
    }
}

 

2 hours ago, duke_meister said:

 



static Pos FoodPos = new Pos(0, 0);

You can replace it with one line of code with built in class Point:


Point foodPos = new Point(0, 0);

@phil67rpg what do you want to add in your code next?


using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace SnakeByPhil_WinFormsGDI
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            CenterToScreen();

            timer1.Interval = 200;

            timer2.Interval = 500;
            timer2.Start();
        }

        int x = 0, y = 0;

        Random rnd = new Random();

        int move = 1;

        Point foodPos = new Point(0, 0);

        private void timer2_Tick(object sender, EventArgs e)
        {
            move = rnd.Next(1, 5);
            foodPos.X = rnd.Next(0, 290);
            foodPos.Y = rnd.Next(0, 290);
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = this.CreateGraphics();
            DrawRectangle(g, 340 + x, 280 + y, Color.Green);
            DrawRectangle(g, 330 + x, 280 + y, Color.Black);
            //DrawRectangle(g, 150 + x, 150 + y, Color.Green);
            //DrawRectangle(g, 140 + x, 150 + y, Color.Black);

            DrawRectangle(g, foodPos.X, foodPos.Y, Color.Red);

            g.Dispose();
        }

        private void DrawRectangle(Graphics g, int x, int y, Color color)
        {
            SolidBrush brush = new SolidBrush(color);
            Rectangle rect = new Rectangle(x, y, 10, 10);
            g.FillRectangle(brush, rect);
            brush.Dispose();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            switch (move)
            {
                case 1:
                    for (int i = 0; i <= 20; i++)
                    {
                        x++;
                    }
                    break;
                case 2:
                    for (int i = 0; i <= 20; i++)
                    {
                        x--;
                    }
                    break;
                case 3:
                    for (int i = 0; i <= 20; i++)
                    {
                        y++;
                    }
                    break;
                case 4:
                    for (int i = 0; i <= 20; i++)
                    {
                        y--;
                    }
                    break;
            }

            if (MouseButtons == MouseButtons.Left)
            {

            }
            Invalidate();
        }
    }
}

 

February 19, 2019 11:07 AM
duke_meister

I just converted my console snake code to GDI. Just to show how a good design can be easily used with any underlying drawing method.

So really, discussion about which is 'harder' is moot.

Phil, happy to take you through the design process step by step if you like.

 

February 19, 2019 11:12 AM
duke_meister
27 minutes ago, 8Observer8 said:

You can replace it with one line of code with built in class Point

Not true. For instance in my version it represents a cell, not a pixel/point.

ed: I could still have used it of course, but I prefer the abstraction.

February 19, 2019 11:30 AM
8Observer8

I have a step-by-step instruction how to make a prototype of 2D Snake Game using GDI. @phil67rpg may be you will read my instruction?

 

 

@phil67rpg it is simple to convert it from GDI to WPF or to OpenGL or even to 3D with OpenGL. I wrote instruction how to convert form GDI to OpenGL 3: https://www.gamedev.net/blogs/entry/2266689-101-snake-winforms-opengl-31/

February 19, 2019 11:30 AM
phil67rpg

hey guys thanks for all the input, is there anyway I can improve the snake movements? do I need to use the for loops I am using?

February 19, 2019 10:11 PM
8Observer8

It is a popular solution how a snake can grow:

SnakeByPhil_WinFormsGDI_PopularSolution.gif.d7a958c8a1bab9d17f4dd45c4071f483.gif


using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace SnakeByPhil_WinFormsGDI
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            CenterToScreen();

            timer1.Interval = 200;
            timer1.Start();
        }

        Random rnd = new Random();
        Point foodPos = new Point(0, 0);

        const int snakeSize = 10;
        Point dir = new Point(snakeSize, 0);
        List<Point> snake = new List<Point>()
        {
            new Point(50, 50)
        };

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = this.CreateGraphics();

            foreach (var cell in snake)
            {
                DrawRectangle(g, cell.X, cell.Y, Color.Green);
            }

            DrawRectangle(g, foodPos.X, foodPos.Y, Color.Red);

            g.Dispose();
        }

        private void DrawRectangle(Graphics g, int x, int y, Color color)
        {
            SolidBrush brush = new SolidBrush(color);
            Rectangle rect = new Rectangle(x, y, snakeSize, snakeSize);
            g.FillRectangle(brush, rect);
            brush.Dispose();
        }

        private void Form1_KeyPress(object sender, KeyPressEventArgs e)
        {
            switch(e.KeyChar)
            {
                case 'd':
                    dir.X = snakeSize;
                    dir.Y = 0;
                    break;
                case 'a':
                    dir.X = -snakeSize;
                    dir.Y = 0;
                    break;
                case 'w':
                    dir.X = 0;
                    dir.Y = -snakeSize;
                    break;
                case 's':
                    dir.X = 0;
                    dir.Y = snakeSize;
                    break;
            }
            Invalidate();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            int newHeadXPos = snake[0].X + dir.X;
            int newHeadYPos = snake[0].Y + dir.Y;

            snake.Insert(0, new Point(newHeadXPos, newHeadYPos));

            snake.RemoveAt(snake.Count - 1);

            if (snake[0].X == foodPos.X &&
                snake[0].Y == foodPos.Y)
            {
                snake.Add(new Point(foodPos.X, foodPos.Y));
                //foodPos.X = rnd.Next(0, Width - snakeSize);
                //foodPos.Y = rnd.Next(0, Height - snakeSize);
            }

            Invalidate();
        }
    }
}

 

February 19, 2019 11:33 PM
phil67rpg

well I put  your code in vs2017 and it works. I think I am going to use a list to move the snake. Do I need to use my for loops?

February 20, 2019 02:38 AM
duke_meister

I think you should start with Tic Tac Toe. That's probably an achievable first step. Well, good luck :)

February 20, 2019 07:39 AM
8Observer8
8 hours ago, phil67rpg said:

I think I am going to use a list to move the snake. Do I need to use my for loops?

Please, read this step-by-step instruction very carefully: https://noobtuts.com/python/snake-game It is the Python language, but it is a very simple instruction where a basic snake theory is described very easy. Please, do it.

February 20, 2019 09:56 AM
8Observer8
8 hours ago, phil67rpg said:

Do I need to use my for loops?

No, you don't. Those loops are wrong.

If you like "for" loop more than "foreach" loop:


foreach (var cell in snake)
{
    DrawRectangle(g, cell.X, cell.Y, Color.Green);
}

You can use "for" loop:


for (int i = 0; i < snake.Count; i++)
{
    DrawRectangle(g, snake[i].X, snake[i].Y, Color.Green);
}

 

February 20, 2019 10:24 AM
8Observer8
On 2/20/2019 at 12:56 PM, 8Observer8 said:

Please, read this step-by-step instruction very carefully: https://noobtuts.com/python/snake-game It is the Python language, but it is a very simple instruction where a basic snake theory is described very easy. Please, do it.

What is bad with this instruction? Why do you dislike it? It describes basics of development of snake prototype. It does not matter that it is in Python. It is very simple to rewrite it to another language. I rewrote it to:

Who disliked it? Why did you make it? I spent my time to make these instructions to help beginners.

February 22, 2019 10:13 AM
phil67rpg

I am working with  your code.

February 22, 2019 06:37 PM
8Observer8

This explanation does not depend on the language and how you draw squares. It is very short and it explains common approach to implement snake movement

I copied this text from here: https://noobtuts.com/python/snake-game

Quote


Okay, back to the snake's movement...

Let's assume the snake already ate something three times. Hence it looks like this (as text version):

 

o
o
o
o

 

If the user would move it to the right, it would then look like this the next time:

 

oo
o
o

 

So the obvious way would be to create an algorithm that first moves the snake's head to the new position and then let's every other entry in our snake list follow the snake's head by one step.

Since this sounds kinda complicated, we will use a little trick:
Instead of moving every single element by one step, we will just remove the last element and put it to the new position.
Here is our wonderful text snake again, this time "x" is the last element:

 

o
o
o
x

 

Now if the player wants to move it to the right, instead of moving the first one to the right and letting everything else follow, we will simply remove the x from the end and put it to the new position:

 

ox
o
o

 

This way it appears that the whole snake moved, even though we just removed the last element and made it the new head.

Note: from a performance side, this is just beautiful. It means that in each update call, instead of doing "n" calculations ("n" is the snake length) we only have to do 2 calculations. This kind of trick can make the difference between 60 fps and 30 fps in bigger games.

Anyway, let's create an algorithm that does that for us. At first we need a function that adds two positions. Example:
(3, 4) + (1, 2) = (4, 6).

 

 

February 22, 2019 07:02 PM
phil67rpg

I have made some changes to observers code. I can get the snake to move randomly about the board. here is my updated code.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace snakegamegdi
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            CenterToScreen();
            timer1.Interval = 200;
            timer1.Start();
            timer2.Interval = 200;
            timer2.Start();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        Random rnd = new Random();
        Point food = new Point(385, 275);
        const int size = 10;
        Point direction = new Point(size, 0);
        List<Point> snakelist = new List<Point>()
        {
            new Point(380,280)
        };

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = this.CreateGraphics();
            foreach (var cell in snakelist)
            {
                DrawRectangle(g, cell.X, cell.Y, Color.Green);
            }
            DrawRectangle(g, food.X, food.Y, Color.Red);
            g.Dispose();
        }

        private void DrawRectangle(Graphics g, int x, int y, Color color)
        {
            SolidBrush brush = new SolidBrush(color);
            Rectangle rect = new Rectangle(x, y, size, size);
            g.FillRectangle(brush, rect);
            brush.Dispose();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            int newXPos = snakelist[0].X + direction.X;
            int newYPos = snakelist[0].Y + direction.Y;
            snakelist.Insert(0, new Point(newXPos, newYPos));
            snakelist.RemoveAt(snakelist.Count - 1);
            if(snakelist[0].X==food.X && snakelist[0].Y==food.Y)
            {
                snakelist.Add(new Point(food.X, food.Y));
            }
            Invalidate();
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            int move = rnd.Next(1, 5);
            switch(move)
            {
                case 1:
                    direction.X = size;
                    direction.Y = 0;
                    break;
                case 2:
                    direction.X = -size;
                    direction.Y = 0;
                    break;
                case 3:
                    direction.X = 0;
                    direction.Y = -size;
                    break;
                case 4:
                    direction.X = 0;
                    direction.Y = size;
                    break;
            }
            Invalidate();
        }
    }
}

 

February 24, 2019 02:30 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement

Latest Entries

asteroids wars

2625 views

plane game

3375 views

rgg platformer

2010 views

win 32 pong

2488 views

bug invaders

2147 views

c# book

2438 views

c# bug invaders

2092 views

c# console snake game

23704 views
Advertisement