Advice on implementing a basic minmax algorithm for Connect-4

I've been working on the GUI portion of my C++ Connect-N game project, and have gotten it to would could charitably be called a working state. However, the game AI, not to put it to finely, stinks.

I was wondering if anyone here has more experience in implementing a minmax algorithm, and can offer any advice on how to get it to play a suitably challenging game.

The minmax code is:

#ifndef __CONNECTN_AI_H__
#define __CONNECTN_AI_H__ 1

#include <vector>
#include "connectnboard.h"

namespace ConnectN
{

    typedef intmax_t Weight;
    typedef uint8_t Depth;
    const Weight infinity = INTMAX_MAX, neg_infinity = INTMAX_MIN;

    struct Node
    {
        Board board;
        Grid_Size column;
        Weight weight;
        Depth depth;
        Node(const Board& b, Grid_Size c, Weight w, Depth d): board(b), column(c), weight(w), depth(d) {};
        Node(const Node& n);
        void operator=(const Node& n);
    }; 


    class Solver
    {
    private:
        Board& board;
        Depth search_depth;
        Node negamax(Node node, Depth depth, Weight alpha, Weight beta, Weight color);
        std::vector<Node> enumerate_moves(Node node);
        void order_moves(std::vector<Node>& children);
        Weight evaluate_move(Node& node);
        Weight evaluate_node(Node& node);
        Weight weight_column(Grid_Size c);

    public:
        Solver(Board& b, Depth d);
        Grid_Size move();

        friend class Board;
    };
}

#endif

and

#include <algorithm>
#include <chrono>
#include <cmath>
#include <random>
#include "connectnboard.h"
#include "connectn_AI.h"

namespace ConnectN
{

    /**
     * 
     *
     */
    Node::Node(const Node& n)
    {
        this->board = n.board;
        this->column = n.column;
        this->weight = n.weight;
        this->depth = n.depth;
    }


    /**
     * 
     *
     */
    void Node::operator=(const Node& n)
    {
        this->board = n.board;
        this->column = n.column;
        this->weight = n.weight;
        this->depth = n.depth;
    }


    /**
     * 
     *
     */
    Solver::Solver(Board& b, Depth d = 3): board(b), search_depth(d)
    {

    }


    /**
     *  
     *
     */
    Grid_Size Solver::move()
    {
        Node top = {this->board, 0, neg_infinity, this->search_depth};
        Node found = this->negamax(top, this->search_depth, neg_infinity, infinity, 1);
        return found.column;
    }


    /**
     * 
     *
     */
    Node Solver::negamax(Node node, Depth depth, Weight alpha, Weight beta, Weight color)
    {

        if (depth == 0 || board.win() == COMPUTER)
        {
            return (Node {node.board, node.column, color * node.weight, depth});
        }
        std::vector<Node> children = enumerate_moves(node);

        order_moves(children);
        Node value = {node.board, node.column, neg_infinity, depth};

        for (auto child : children)
        {
            value.column = child.column;
            Node recursive_value = negamax(child, depth - 1, -beta, -alpha, -color);
            value.weight = std::max(value.weight, -recursive_value.weight);
            alpha = std::max(value.weight, alpha);
            if (alpha >= beta)
            {
                break;
            }
        }

        return value;
    }


    /**
     * 
     *
     */
    std::vector<Node> Solver::enumerate_moves(Node node)
    {
        std::vector<Node> children;
        for (Grid_Size i = 0; i < node.board.size(); i++)
        {
            Node child = {node.board, i, 0, static_cast<Depth>(node.depth-1)};
            if (!child.board.add_at(i))
            {
                continue;
            }
            if (child.depth != this->search_depth)
            {
                child.board.switch_player();
            }
            child.weight = evaluate_move(child);
            children.push_back(child);
        }
        return children;
    }


    /**
     * 
     *
     */
    void Solver::order_moves(std::vector<Node>& children)
    {
        std::sort(children.begin(),
                  children.end(), 
                  [](Node first, Node second)
                      {
                          return (first.weight < second.weight);
                      });
    }


    /**
     * 
     *
     */
    Weight Solver::evaluate_move(Node& node)
    { 
        Grid_Size size = node.board.size();
        Weight weight = 0;
        Grid_Size column = node.column;
        Grid_Size midpoint = std::ceil(size/2);

        // add weight depending on whether the token is on the 
        // center column(s).
        if (size % 2)
        {
            if (node.column == midpoint)
            {
                weight += 4; 
            } 
        }
        else
        { 
            // if there are two central columns, weight half as much
            // as you would if there is only one
            if (column == midpoint-1 || column == midpoint)
            {
                weight += 2; 
            }
        }

        weight += evaluate_node(node);
        return weight;
    }

    /**
     * Weight Solver::weight_column(Grid_Size c) - 
     * @param c - total number of 
     */
    Weight Solver::weight_column(Grid_Size c)
    {
        Weight weight = 0;
        Grid_Size max = this->board.winning_count;
        Grid_Size midpoint = std::floor(max/2);

        if (c >= this->board.winning_count)
        {
            // winning move, weight it the maximum amount
            weight = 1000;
        }
        else
        {
            // for every token beyond half the winning amount,
            // increase the weighting by 2
            Weight weighted_count = c - midpoint;
            weight = std::max(0, static_cast<int>(weighted_count+1)) * 2;
        }

        return weight;
    }

    /**
     * Weight Solver::evaluate_column(Node& node)
     * - scan the neighboring square of a given square to see if there 
     *   is a winning sequence.
     * @param node - version of board to evaluate
     */
    Weight Solver::evaluate_node(Node& node)
    {
        Weight weight = 0;
        Player p = node.board.current_player();
        Grid_Size size = node.board.size();    
        Grid_Size offset = node.board.winning_count, 
            target = static_cast<Grid_Size>(node.board.winning_count - 1),
            row = std::max(0, node.board.column_top(node.column) - 1),
            column = node.column;

        bool check_up = (row < (size - target)),
            check_left = (column > offset), 
            check_right = (column < (size - offset));

        if (check_right)
        {
            Grid_Size count = 1;
            for (Grid_Size c = column; c < std::min(size, column + offset) && (node.board.grid[row][c] == p); c++, count++)
            {
                // iterate through
            }
            weight += weight_column(count); 
        }

        if (check_up)
        {
            Grid_Size count = 1;

            for (Grid_Size r = row; (r < std::min(size, row + offset)) && (node.board.grid[r][column] == p); r++, count++)
            {
                // iterate through
            }
            weight += weight_column(count);
        }

        if (check_left)
        {
            Grid_Size count = 1;
            for (Grid_Size r = row, c = column, count = 0; 
                 (r < (row + offset)) && (c >= (column - target)) && (node.board.grid[r][c] == p); 
                 r++, c--, count++)
            {
                // iterate through
            }
            weight += weight_column(count);
        }

        if (check_right)
        {
            Grid_Size count = 1;
            for (Grid_Size r = row, c = column, count = 0; 
                 (r < std::min(size, row + offset)) && (c < std::min(size, column + offset)) && (node.board.grid[r][c] == p); 
                 r++, c++, count++)
            {
                // iterate through
            }
            weight += weight_column(count);
        }

        return weight;
    }

}

Making levels for game

Working on a game for a friends daughter for her 6th birthday. Its a scrolling game where the player will be Snoopy and they'll be flying around on his doghouse collecting Woodstock (Which are flying around the screen) for each level (There will be 4 levels). At the end of each level, the game will have an intermission and show a 10sec video of Snoopy dancing. The background will play the Peanuts theme song. Ive figured out everything except how to make levels for the game. I've tried using a timer but that didn't seem to work very well. Everytime Ive tried to include the block of code I've written the screen doesn't add it and returns back to step one of asking a question on this forum.

How to be the next Pubg maker! Learn Game Development now.

How to be the next Pubg maker! Learn Game Development now

We all know how fun it is to play games in our leisure time and we enjoy it to a certain point but just imagine this; A specific type of game that you always wanted to play but you cannot find it either on the app store or play store and guess what? You develop the exact game on your own and add whatever features you want to it!

This is not the only exciting thing about Game Development, you can start selling it to make some money too and we all love money dont we? Getting an experience like this is simply out of the world but here at Ideoversity, which is the best training institute in Pakistan, we make it happen by providing the game development course under the guidance of the best instructors in the industry. You will learn concept generation, design, build, test and release. Become the game-changing game developer by starting your course with us now!

Requirements
Have a good grip of the English language.
You should know the basic operations of using a computer with ease.
Must be at least 16 and above of age.
Willing to put in effort and creativity.

Things you will learn

In the game development course, each module of your degree is planned to look and function like your industry from your workspaces to your projects, to your schedule. With an emphasis on projects that prove your experience to future employers, youll be building experience and a portfolio while learning in ideoversity training institute

How will you get a job?
There are various methods based on which route youre taking.

Freelance

To become a freelancer, you require:

A strong portfolio
A solid pitch
Cold emailing skills
The cold emailing skills and the solid pitch are a little unique and will require some quality research but dont worry, you will find many free resources online.

Decide your niche, create your blog and your LinkedIn profile around that niche. Then research companies that could benefit from app or game development, and send them an email pitching the idea.

That is a very basic version of what you need to do, but it should be enough to get you started. Its a lot of work, so break it down into little steps as tiny steps lead to success. STUDIO
Getting a job at a studio is similar, you still need a strong portfolio for it too.

As discussed earlier, portfolios are going to set you apart from your peers. Anyone can use the existing roadmap of not getting out of their comfort zone and get a loan to go to university for years and get a degree but not everyone can put a game together quite like you can. No one has your unique experiences. No one has your specific skill set. To shine brighter than others simply apply to the best game development course in Pakistan offered by the best training institute; Ideoversity.

What you need to know
Game developers can be a programmer, sound designers, an artist, a designer, or many other fields available worldwide.

Game Development can be done by a large Game Development Studio or by a single individual. Be it small or large, just do what you like as long as it lets the player interact with content and is able to control the games elements, you can call it a game.

To get involved in the Game Development process, you do not need to do coding. Artists may create and design assets, while a Developer might focus on programming a specific element in the game such as the health bar of the player in-game. A Tester plays the game and checks for faults and possible improvements. You can become any by joining the game development course with Ideoversity training institute.

To resolve problems that game frameworks had, tools like libGDX and OpenGL were developed. They helped game development to be a lot faster and easier, providing lots of pre-made functions and features. However, it was still hard to enter the industry or understand a framework for someone coming from a non-programmer background, a common cause in the game development scene. To join the game development course apply now to ideoversity training institute

That was when game engines like Construct, Game Maker, Unity, and Unreal were developed. Generally, an engine has everything that a framework had, but with a more friendly approach by using a graphic user interface (GUI) and helping with the graphic development of the game.

In some cases, like Game Maker and Construct, the amount of pre-made functions is so big that people with no previous programming skills could build a game from scratch, really expanding the scene and making game development accessible for almost anyone. You can also do magic by joining the game development course at ideoversity training institute.

Game Engines

Many developers choose to develop a game using a Game Development Engine.

Game Engines can make the process of creating a game much easier and enable developers to reuse lots of functionality. It also takes care of rendering for 2D and 3D graphics, physics and collision detection, sound, scripting, and much more.

Some Game Engines have a very steep learning curve such as CryEngine or Unreal Engine. Yet, other tools are very accessible to beginners and some do not even need you to be able to write code to create your game, e.g. Construct 2.

The Unity Game Engine ranges somewhere in the middle, while it is beginner-friendly, some popular and commercial games have been built using Unity (e.g. Overcooked, Superhot).

The BuildBox game engine is basically for developing hyper-casual games. To join the game development course just visit the website of ideoversity training institute.

Typical Game Engines

CryEngine
Unreal Engine
Unity Game Engine
Game Maker
Construct 2 or 3
Twine
Source
Frostbite
Buildbox

Shooting fish game

I want to make a fish shooting game, but I don't know where to start maybe here friends can give me directions please help for my learning

Can u help me I am making a game in pygsme pygame in python so when I run t

Can u help me I am making a game in pygsme pygame in python so when I run the program it appears a blank black screen instead of the image that I hve upload in pygame to make game so actuaaly when I run the program it appears blank black screen and when I close the program the image is shown a couple of seconds and and it close the window so pls can u help me in this

Why is my Key Listener not working within the code below?

import javax.swing.*;
import javax.swing.plaf.basic.BasicTreeUI;
import java.awt.*;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class GamePanel extends JPanel implements Runnable, KeyListener{
    final int originTileSize = 16; //The Size of the tiles, or grids
    final int scale = 3;
    final int tileSize = originTileSize * scale;
    final int screenCol = 10;
    final int screenRow = 12;
    final int screenHeight = screenCol * tileSize; //480 pixels
    final int screenWidth = screenRow * tileSize; //576 pixels
    int FPS = 60;
    boolean upPressed = false, downPressed = false, rightPressed = false, leftPressed = false;

    Thread gameThread;


    int playerX = 100;
    int playerY = 100;
    int playerSpeed = 4;

    public GamePanel(){
        this.setPreferredSize(new Dimension(screenWidth, screenHeight));
        this.setBackground(Color.black);
        this.setDoubleBuffered(true);
        this.addKeyListener(this);
        this.setFocusable(true);
        this.requestFocus();

        //Changes the frame so the panel comes out like this

    }

    public void startGameThread(){
        gameThread = new Thread(this);
        //Puts everything in the Class into the thread
        gameThread.start();
        //automatically calls the run method
    }


    @Override
    public void run() {


        double drawInterval = 1000000000/FPS; //0.1666 seconds
        double nextDrawTime = System.nanoTime() + drawInterval;

        while(gameThread != null){
            update();

            repaint();

            try {
                double remainingTime = nextDrawTime - System.nanoTime();
                remainingTime = remainingTime/1000000;

                if(remainingTime < 0){
                    remainingTime = 0;
                }

                Thread.sleep((long) remainingTime);

                nextDrawTime += drawInterval;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
//While this game loop is here it will keep running whatever is inside

    }
    private void update() {

        if(upPressed){
            playerY -= playerSpeed;
        }
        else if(downPressed){
            playerY += playerSpeed;
        }
        else if(rightPressed){
            playerX += playerSpeed;
        }
        else if(leftPressed){
            playerX -= playerSpeed;
        }
    }
    public void paintComponent(Graphics g){
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D)g;

        g2.setColor(Color.white);

        g2.fillRect(playerX, playerY, tileSize, tileSize);

        g2.dispose();
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
        System.out.println("Pressed W");
        int code = e.getKeyCode();
        if(code == KeyEvent.VK_W){
            System.out.println("Press W");
            upPressed = true;
        }
        else if(code == KeyEvent.VK_A) {
            System.out.println("Pressed A");
            downPressed = true;
        }
        else if(code == KeyEvent.VK_D) {
            System.out.println("Pressed D");
            rightPressed = true;
        }
        else if(code == KeyEvent.VK_S) {
            System.out.println("Pressed S");
            downPressed = true;
        }

    }

    @Override
    public void keyReleased(KeyEvent e) {
        int code = e.getKeyCode();
        System.out.println(code);
        if(code == KeyEvent.VK_W) {
            upPressed = false;
        }
        else if(code == KeyEvent.VK_A) {
            downPressed = false;
        }
        else if(code == KeyEvent.VK_D) {
            rightPressed = false;
        }
        else if(code == KeyEvent.VK_S) {
            downPressed = false;
        }

    }
    //This is where we will keep a game loop. A thread is where it'll always keep running and so a game loop will always be running in here unless closed.
}

Is SFML good for C++ newbies?

I am just learning C++. I haven't made any games with SFML or anything like that. Just wondering whether SFML would be easy for a newbie like me. I am planning on using it after I finish learncpp.com. I am currently at the header guards section right now. Also, what do you... <DANIWEB>-users think of learncpp?

Help with homing missile I have one part working

Making a scrolling space shooting video game in C# where the player will fight one on one with their opponent. I was able to figure out how to make the missile go up if the opponent was above the player. But, I can't seem to make it work if the opponent is below or right infront of the player. Can someone help me? I know the answer is right under my nose.

The function below handles the movement of the missile

 void movemissile()
        {
            foreach (Control y in this.Controls)
            {
                if (y is PictureBox && y.Tag == "missile") 
                {

                    //y.Left += 100;//x.Top -= 10;
                    if (y.Left > enemy.Left)//<100
                    {
                        y.Left += 10;
                        //this.Controls.Remove(y);
                    }

                    //plyer missile goes up if opponent is above
                    if (y.Top > enemy.Top)
                    {
                        y.Left += 10;
                        y.Top -= 20;
                        y.Left += 10;
                        //this.Controls.Remove(y);
                    }
                    y.Left += 100;//x.Top -= 10;
                    if (y.Top > enemy.Left)//<100
                    { 
                        this.Controls.Remove(y);
                    }
                }
            }
        }

        This function handles drawing the missile of the player for the game.
                void Missile()
        {
            PictureBox m = new PictureBox();
            m.SizeMode = PictureBoxSizeMode.AutoSize;
            m.Image = Properties.Resources.Missile1;
            m.BackColor = System.Drawing.Color.Transparent;
            m.Tag = "missile";
            m.Left = Player.Left + 100;//moves bullet left or right
            m.Top = Player.Top + 55;//55 is perfect
            this.Controls.Add(m);
            m.BringToFront();
        }

The Unknown Design Pattern

If you care about software, you have probably heard about design patterns: MVC, decorators, factories, etc. But there's an awesome design pattern that’s perfect for modeling complex behaviors, but it’s not well-known outside of the game industry.

We’ve built a narrative sci-fi MMORPG named Tau Station. Like many devs, we were quickly hit with the problem of developing complex items. At first, it looked like we wanted to create an Item class and inherit from that.

2D game pause between player shots

I kind of figured out how to put a pause in my 2d game when the player shoots. The problem is that when the player shoots once, the game will continue to shoot continously, even after the player has stopped shooting. Can someone please help me?

        void Bullet()//draws the players ship ammo
        {
            PictureBox bullet = new PictureBox();
            bullet.SizeMode = PictureBoxSizeMode.AutoSize;
            bullet.Image = Properties.Resources.Shoot;
            bullet.BackColor = System.Drawing.Color.Transparent;
            bullet.Tag = "bullet";
            bullet.Left = playersuper.Left + 100;//moves bullet left or right
            bullet.Top = playersuper.Top + 50;//55 is perfect                    
            this.Controls.Add(bullet);
            bullet.BringToFront();
            shootimer.Interval = 1000;
            shootimer.Enabled = true;
        }
         private void shootimer_Tick(object sender, EventArgs e)
        {
            fire = new SoundPlayer("shooting.wav");
            fire.Play();
        }
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            bool playing = false;
            if (e.KeyCode == Keys.Right)
            {
                right = true;
            }
            if (e.KeyCode == Keys.Left)
            {
                left = true;
            }
            if (e.KeyCode == Keys.Up)
            {
                up = true;
            }
            if (e.KeyCode == Keys.Down)
            {
                down = true;
            }
            if (e.KeyCode == Keys.Space)
            {
                Bullet();
            }
            if (e.KeyCode == Keys.A)
            {
                if (nomissiles.Value >= 10)
                {
                    pc.miss--;
                    nomissiles.Value -= 10;
                    A = true;
                    Missile();
                }
            }
            if (e.KeyCode == Keys.Z)
            {
                PictureBox robot = new PictureBox();
                robot.SizeMode = PictureBoxSizeMode.AutoSize;
                robot.Image = Properties.Resources.Bioroidd;
                robot.BackColor = System.Drawing.Color.Transparent;
                ((PictureBox)playersuper).Image = Properties.Resources.Bioroidd;
                transform = new SoundPlayer("transforming.wav");
                transform.Play();
            }
            if (e.KeyCode == Keys.X)
            {
                PictureBox gerwalk = new PictureBox();
                gerwalk.SizeMode = PictureBoxSizeMode.AutoSize;
                gerwalk.Image = Properties.Resources.Gurwalk;
                gerwalk.BackColor = System.Drawing.Color.Transparent;
                ((PictureBox)playersuper).Image = Properties.Resources.Gurwalk;
                transform = new SoundPlayer("transforming.wav");
                transform.Play();
            }
            if (e.KeyCode == Keys.C)
            {
                PictureBox fighter = new PictureBox();
                fighter.SizeMode = PictureBoxSizeMode.StretchImage;
                fighter.Image = Properties.Resources.fighter;
                fighter.BackColor = System.Drawing.Color.Transparent;
                ((PictureBox)playersuper).Image = Properties.Resources.fighter;
                transform = new SoundPlayer("transforming.wav");
                transform.Play();
            }
            if (e.KeyCode == Keys.P)
                GameTimer.Stop();
            if (e.KeyCode == Keys.S)
                GameTimer.Start();
        }

Python Tkinter: mouse drag and drop more than 1 image

Hi, Im creating a canvas and inserting an image. I'm using bind to move the image with my mouse. It works, but whenever I add another image, it doesn't work. When I try to move any images, only image1 moves and image 2 dissappears.

Any ideas would help, thanks

Here's my code:

from tkinter import *

root = Tk()
root.title("Testing...")
root.geometry("800x600")
w = 600
h = 400
x = w / 2
y = h / 2

my_canvas = Canvas(root, width=w, height=h, bg="white")
my_canvas.pack(pady=20)

img = PhotoImage(file="bbishop.png")
my_image = my_canvas.create_image(260, 125, anchor=NW, image=img)
img2 = PhotoImage(file="brook.png")
my_image2 = my_canvas.create_image(200, 325, anchor=NW, image=img2)

def move(e):
    # e.x
    # e.y
    global img, img2
    img = PhotoImage(file="bbishop.png")
    my_image = my_canvas.create_image(e.x, e.y, image=img)
    #my_label.config(text="Coordinates: x: " + str(e.x) + " y: " + str(e.y))
    img2 = PhotoImage(file="brook.png")
    my_image2 = my_canvas.create_image(e.x, e.y, 325, image=img2)

my_label = Label(root, text="")
my_label.pack(pady=20)

my_canvas.bind('<B1-Motion>', move)
root.mainloop()

mouse locke for value specific

Hello, I created a C ++ program, which I linked to a game.
I gave an address on which I can give actions, for example mouse event, it works.
My goal is to insist that when this value is correct the mouse will stay on this object even if I am moving where it does.
until it passes behind a wall where the changed value becomes 0.

Move image using bitmap

Working on a game and I made a separate class to handle the players enemies (Its a scrolling type 90s game). I know if I use picturebox and put it on form1 I can say for example....
enemy1.Left > 90;
My question is how would I do something like that with bitmap? I figured out how to put the image on form1, but I can't figure out how to make it move.