Projects and products

Go code-diving

Mr. B diving in the ocean

Have no fear!

Click the headlines below to learn about my projects and products through descriptions, program functionality examples, code examples and the possibility of reading and/or downloading the entire code.

Task

Evaluate and redesign the website www.bella6000.dk.

Solution

The solution consists of two things:

  • The website bellaitaliaredesign.wordpress.com in which of all my thoughts regarding the evaluation and redesign are presented, i.e. described and illustrated.
  • An Adobe XD-file containing the redesign.
Images
An image of the homepage of the existing website. It is not beautiful or well-proportioned

The homepage of the existing website

An image of the upper part of the homepage of my prototype. It is more beautiful and well-proportioned than the existing homepage

The upper part of the homepage of my prototype

My style tile showing the different fonts, colors and backgrounds used in my prototype

My style tile

Click this button to download all of the files:

Task

Make a webpage where you can choose many different dishes and then get a generated shopping list.

Solution

The page “Food” here on this website.

On the page, the user can select dishes and get the appropriate shopping list, get a random shopping list for certain dishes based on the users’ criteria, and finally the user can search dishes based on ingredient.

Emphasis in the development was on the user not having to ever start over selecting the different things. I succeeded in this making the whole thing one big form, where everything is sent every time. Thereby, the user doesn’t have start over at any time, and another great benefit is for example, that the search result remains visible while other data are changed, sent and received.

The PHP solution connects to a database (made by me), and I have taken the necessary means to avoid SQL injection attacks.

Click this button to go to the page:

Task

Investigate the usage and effects of Security Headers in Denmark and worldwide.

Solution

A report and a powerpoint presentation, both of which can be downloaded in the bottom.

The following overview of Security Headers’ functions and effects is part of my solution:

An overview of the functions and effects of 6 Security Headers

An overview of the functions and effects of 6 Security Headers

The conclusion is as follows:

Samlet set viser resultaterne af undersøgelserne, at arten og graden af den generelle SH-implementering er særdeles mangelfuld.

Den generelle hjemmesidebruger kan på ingen måde regne med at være beskyttet af SH på selv de mest populære hjemmesider, hvad end det drejer sig om banker, nyhedsmedier eller de allerstørste virksomheder.

Behovet for IT-sikkerhed, det vil sige brugerbeskyttelse i forbindelse med hjemmesidebesøg i denne sammenhæng, er vokset i takt med internettet, datastrømmen og antallet af forbindelser, men behovet er altså langt fra dækket i øjeblikket, og den generelle online-sikkerhed lider voldsomt derunder.

Den generelle bruger er sig slet ikke Security headers, deres funktioner og farerne ved deres fravær bevidst, så det er et stort problem og udtryk for uansvarlighed, når langt størstedelen af hjemmesideindehavere ikke benytter sig af en generelt set så lettilgængelig brugerbeskyttende mekanisme, som Security headers udgør.

Click this button to download all of the files:

Task

Within the concepts and approaches of Unified Process, investigate and describe what people, considerations, events and diagrams would be relevant to make part of the process of transforming the board game “Flamme Rouge” into a computer game.

Solution

A powerpoint presentation, which among other things contains the following:

  • Description of Unified Process
  • Design Thinking
  • Vision
  • Use Case Model (containing examples of brief, casual and fully dressed use cases)
  • Business Process Model (Flowchart Diagram)
  • Iteration Plan
  • Evaluation (of Inception)
  • Domain Model
  • Design Model
  • Implementation of Start Up Use Case
  • Evaluation (of Elaboration)

Click this button to download all of the files:

Task

Transform the board game “Flamme Rouge” into a computer game.

Solution

The board game has been digitalized using Visual Studio and C#, and among the most prolific ingredients are:

  • Inheritance
  • Interface (class)
  • Design Patterns: Singleton, Prototype
  • Database connection for storing and retrieving game results
A screenshot of the game in action

A lot of colors are used in the console to depict cards, riders and the course

The solution is part of an exam I did in a course called Advanced Programming. I solved 3 other tasks as well in that exam, so those are also be part of the files for download below. To solve the other tasks I used Dijkstra, Graph Theory, Depth First Search, Breadth First Search among other things, which is all very interesting stuff!

It’s all described in the report and partly in the code. (All of the code is in the report).

Click this button to download all of the files:

Task

Make a website, where I present my projects, products and learning progress in detail.

Solution

The website you are currently visiting.

Three months ago I had no knowledge at all about the subject. I then followed the course Beginner Full Stack Web Development: HTML, CSS, React & Node (30 hrs) on Udemy and made this website. Through HTML5, CSS3 and JavaScript, I have used the following elements/techniques:

  • Google fonts
  • Jumbotron
  • Font awesome
  • Progressive images
  • Image-transformation
  • CSS Grid
  • Window width responsivity
  • Navbar
  • Bootstrap 4: Accordion, Carousel, Modal, Rows and columns
  • JavaScript: Image-slideshow

Do feel free to look around!

Click the buttons below to watch the HTML files, CSS files and Javascript files in their complete form (as they were in June 2019):

Click this button to download all of the files (as they were in June 2019):

Task

Design, normalize and implement a database for a small publisher, and then extract data from it.

Solution

The design of the database can be seen from the relation diagram below:

Klasserelationsdiagram

The table ‘boggenretildeling’ seemingly has no primary key, but actually its two fields together take on that role

The database shown is in the 3rd normal form.
The implementation of the database and the extraction of data from it is done through an SQL-script. Here is an extract from the script, where the table ‘byer’ is created:

CREATE TABLE postnumre
(postnummer          CHAR(4) NOT NULL PRIMARY KEY,
bynavn                    VARCHAR(30) NOT NULL,
CONSTRAINT ligegyldigt_postnummer_check CHECK
    (LENGTH(postnummer) = 4)
);

The wish to make sure that ‘postnummer’-entries consist of exactly four characters is not fulfilled by the constraint in MySQL (which is the program I used for this database), and therefore a stored procedure, a before insert trigger and a before update trigger are created:

DELIMITER $
CREATE PROCEDURE postnummer_check(IN postnummer CHAR(4))
BEGIN
    IF LENGTH(postnummer) <> 4 THEN
        SIGNAL SQLSTATE '45000'
           SET MESSAGE_TEXT = 'postnumre.postnummer skal bestå af præcis 4 cifre';
    END IF;
END$
DELIMITER ;

DELIMITER $
CREATE TRIGGER postnumre_before_insert BEFORE INSERT ON postnumre
FOR EACH ROW
BEGIN
    CALL postnummer_check(new.postnummer);
END$
DELIMITER ;

DELIMITER $
CREATE TRIGGER postnumre_before_update BEFORE UPDATE ON postnumre
FOR EACH ROW
BEGIN
    CALL postnummer_check(new.postnummer);
END$
DELIMITER ;

After constructing all of the tables, they are filled with data, from which a lot of new data is then extracted using a variety of queries.

Click the button below to watch the sql-script in its complete form:

Click this button to download the sql-script:

Task

Make a small administrative system for a public library containing different material classes and having a GUI part. It should at least give the user the possibility of getting a list of all materials, of searching for, borrowing and returning a certain material, and various warnings about impossibilities should pop up.

Solution

At the core of the program we have the superclass ‘materiale’ and its four different subclasses, ‘bog’, ‘film’, ‘LP’ and ‘spil’ that all inherit from ‘materiale’. Their attributes are used by the GUI to let the user do what was asked for in the task description. Several other functionalities exist however, among these are:

  • Delete material
  • Reserve material
  • Create new material (with a lot of parameter checking going on)
  • Save current state, i.e. binary saving of the objects in an external file
  • Recreate the original database of materials

Below you see screen shots of the program in action:

The complete list of materials is shown in the GUI

The complete list of materials is shown

A new material is being created in the GUI

A new material is being created

A message from the GUI tells the user, that the material with ID=15 can't be borrowed and then asks, if the user would like to reserve it

The material with ID=15 can't be borrowed. Would you like to reserve it?

The search function relates to both the title, year, artist/company and console

The search function relates to both the title, year, artist/company and console

The most interesting and maybe even cool thing about the program might be its use of binary saving. It is done using the module ‘pickle’, and the save performing functions are all in the file ‘data_bevaring.py’, which - along with all of the other files - can be seen in its complete form by clicking the buttons in the bottom. The following extracts show how the ‘materialeliste’, i.e. a list containing material objects, is saved and loaded:

def gem_materialeliste(materialeliste):
    with open(filnavn, "wb") as gm:
        pickle.dump(materialeliste, gm, pickle.HIGHEST_PROTOCOL)

The function ‘gem_materialeliste’ takes a list as its parameter, which is then saved (dumped) in the binary file entitled ‘filnavn’ at the location where the .py-file of the programming running is located.

def hent_gemt_materialeliste():
    with open(filnavn, "rb") as gm:
        gemt_materialeliste = pickle.load(gm)
        return gemt_materialeliste

The function ‘hent_gemt_materialeliste’ first loads and then returns the list entitled ‘filnavn’ at the location where the .py-file of the programming running is located.
Let’s also take a look at the constructor of the superclass ‘Materiale’:

class Materiale:
   
def __init__(self, idnr=0, titel="N/A", antal=0, antal_udlaan=0,
                 reservationer=0, aarstal=0):
        self.idnr = idnr
        self.titel = titel
        self.antal = antal
        self.antal_udlaan = antal_udlaan
        self.reservationer = reservationer
        self.aarstal = aarstal
        self.medie = "?"

No object is ever made from this class. It serves instead entirely as a superclass on the base of which e.g. objects of the subclass ‘Bog’ are created:

class Bog(Materiale):
   
def __init__(self, idnr=0, titel="N/A", antal=0, antal_udlaan=0,
                 reservationer=0, aarstal=0, forfatter="N/A", antal_sider=0):
        super(Bog, self).__init__(idnr, titel, antal, antal_udlaan,
                                  reservationer, aarstal)
        self.forfatter = forfatter
        self.antal_sider = antal_sider
        self.medie = "Bog"

Click the buttons below to watch the python files in their complete form:

Click this button to download all of the files:

Task

Make a small computer game, where the player tries to get out of a mine field alive.

Solution

Beyond solving the task, the following extra elements were put into the game as well (the code relating to the parts in bold will be shown and explained below):

  • Player login (through player name)
  • Player logout
  • Topscorer list (saved as a list in a separate json-file, which the program itself creates when needed)
  • Introduction to the game within the game
  • An introductory game
  • 3 levels (comprising several different randomized bomb-patterns)
  • Dimensions of the mine field totally up to the player with no upper limit (the level-based and randomized pattern is then layed out within the chosen dimensions)
  • Point system based on the level and dimensions of the field

Here, you see screen shots of the main menu and the ingame game introduction:

The main menu gives you different options

Main menu

The ingame game introduction explains the principles of the game

Ingame game introduction

Here, you see a player making a custom board and then trying to make it out alive:

The player is making a custom board

The player is making a custom board

The game board

Let the game begin! The player is marked by 'P'

The player advances

First steps

The player advances further

Now don't you blow up on me! (Game title)

The player stepped on a bomb

Now that's a shame :-(

Now it’s time for some in-depth explaining of the code.

When the program is started, the following piece of code takes care of the course of events. First of all, the topscorer list is loaded and put into a variable, and then the player is greeted and put into a variable as well.
After those few startup functions and variables have been dealt with, a while-loop is started and runs until the program is stopped by the user. The while-loop always starts with printing the main menu, and the user’s choice (‘actual_choice’) then decides where to go next. Whenever the process there is finished, the while-loop runs again from the top, unless of course the user chooses to exit the program.

"""
THE PROGRAM IS STARTED HERE
"""

# Initiation of topscorer list and start screen
actual_topscorer_list = load_topscorer_list()
start_screen()

# Player registration and personal welcome
unchecked_player = enter_name_return_player_list()
welcome_back = player_list_update(unchecked_player, actual_topscorer_list)
actual_player = unchecked_player
welcome(actual_player, welcome_back)

# Main menu is printed and returned to until game is closed
while True:
    print_main_menu_options()
    actual_choice = choose_main_menu_option_return_int_choice()
    if actual_choice == 1:
        points_scored = start_game([5, 3, 0])
        if points_scored != 0:
            add_player_points(actual_player, points_scored)
            topscorer_list_update(actual_player, actual_topscorer_list)
            save_topscorer_list(actual_topscorer_list)
    elif actual_choice == 2:
        start_game_list = prepare_start_game_return_start_game_list()
        points_scored = start_game(start_game_list)
        if points_scored != 0:
            add_player_points(actual_player, points_scored)
            topscorer_list_update(actual_player, actual_topscorer_list)
            save_topscorer_list(actual_topscorer_list)
    elif actual_choice == 3:
        print_topscorer_list(actual_topscorer_list)
    elif actual_choice == 4:
        game_introduction()
    elif actual_choice == 5:
        unchecked_player = enter_name_return_player_list()
        welcome_back = player_list_update(unchecked_player,
                                          actual_topscorer_list)
        actual_player = unchecked_player
        welcome(actual_player, welcome_back)
    elif actual_choice == 6:
        exit_game(actual_player)
    else:
        print("Something went wrong in the main menu")

The most interesting parts of the code comes into play when the player decides to actually play the game. At that point, the player chooses ‘1’ (standard board) or ‘2’ (custom board) in the main menu. As can be seen in the code above, the ‘actual_choice’ is then ‘1’ or ‘2’, both of which in turn calls the function ‘start_game()’. That function takes a list as its parameter, and let’s now have a look at how that list is put together when the custom board is chosen. Firstly, the function ‘prepare_start_game_return_start_game_list()’ is called:

# GAME FUNCTIONS (1 & 2 IN MAIN MENU)
def prepare_start_game_return_start_game_list():
    """Returns list of chosen options [rows, columns, level]"""
   
while True:
        rows = input("\nHow many rows do you want? ")
        columns = input("How many columns do you want? ")
        try:
            rows = int(rows)
            columns = int(columns)
        except ValueError:
            print("You didn't type in whole numbers. Try again.")
            continue
        else:
            if not (rows >= 4 and columns >= 4):
                print("You have to choose at least 4 rows and 4 columns. "
                      "Try again.")
                continue
        break
    possible_levels = []
    if rows >= 4 and columns >= 4:          # necessarily true
        possible_levels.append(1)
    if rows >= 6 and columns >= 6:
        possible_levels.append(2)
    if rows >= 11 and columns >= 11:
        possible_levels.append(3)
    print("\nThe following levels are available:")
    for number in possible_levels:
        print("\tLevel " + str(number))
    while True:
        choose_level = input("\nType the number of the level you "
                             "want to try: ")
        try:
            level_choice = int(choose_level)
        except ValueError:
            print("You didn't type in a whole number. Try again.")
            continue
        else:
            if level_choice in possible_levels:
                break
            else:
                print("You didn't type in one of the numbers. Try again.")
    return [rows, columns, level_choice]

After making sure the player is typing in whole numbers greater than ‘3’, levels represented by numbers are appended to an empty list, which the player then is told to choose from. In the end, a list containing the number of rows and columns and the chosen level is returned.

The list returned from the function ‘prepare_start_game_return_start_game_list()’ is then passed on as an argument into ‘start_game()’, which starts like this:

def start_game(start_game_list):
    """Accepts a list containing [rows, columns, level_choice]
    and starts the game"""
   
rows = start_game_list[0]
    columns = start_game_list[1]
    level = start_game_list[2]

    start_again = True
    while start_again:
        original_game = GameEngine(rows, columns)

The elements of the argument (a list) are put into variables, and then GameEngine() is called, which makes a grid (a board) without any bombs:

import copy
import random

class GameEngine():
    """
    Instantiation of a point grid with rows and columns,
    where each point is shown as 'o' and has no bomb.
    An extra row is added in the end, where each point
    is shown as ' ' and has no bomb. Those points are for
    the starting zone.
    The coordinates are structured like this:
        (0,0)   (0,1)   (0,2)
        (1,0)   (1,1)   (1,2)
        (2,0)   (2,1)   (2,2)
    """
   
def __init__(self, rows, columns):
        self.rows = rows
        self.columns = columns

        self.row = []                                           # the grid
        self.grid = []                                          # the grid
        self.dictionary = {'show': 'o', 'bomb': False}          # the grid

        self.start_row = []                                     # start zone
        self.start_dictionary = {'show': ' ', 'bomb': False}    # start zone

        for x in range(columns):                                # the grid
            self.row.append(copy.deepcopy(self.dictionary))
        for y in range(rows):                                   # the grid
            self.grid.append(copy.deepcopy(self.row))
        for z in range(columns):                                # start zone
            self.start_row.append(copy.deepcopy(self.start_dictionary))
        self.grid.append(copy.deepcopy(self.start_row))

The constructor of the class ‘GameEngine’ creates a 2-dimensional grid with each coordinate containing a dictionary, that contains low level graphics and bomb information.

What happens next in ‘start_game()’ is some randomized bomb pattern selection based on the chosen level, which is then layed out over the previously created grid. The laying out of bombs happens in the GameEngine-class. Here is an example:

# Minimum size grid: 6 rows x 6 columns
def pattern_four(self):
    for row in range(self.rows):
        if (row + 6) % 6 == 0:
            for column in range(self.columns):
                if (column + 6) % 6 == 0:
                    self.put_bomb(row, column)
                if (column + 5) % 6 == 0:
                    self.put_bomb(row, column)
                if (column + 4) % 6 == 0:
                    self.put_bomb(row, column)
                if (column + 1) % 6 == 0:
                    self.put_bomb(row, column)
        elif (row + 5) % 6 == 0:
            six_positions_counter = 0
            for six_column_positions in range(self.columns // 6):
                random_position = random.randint(0, 5)
                self.put_bomb(row, six_positions_counter * 6 +
                              random_position)
                six_positions_counter += 1
            if self.columns % 6 != 0:
                rest_positions = self.columns % 6
                random_position = random.randint(0, rest_positions - 1)
                self.put_bomb(row, six_positions_counter * 6 +
                              random_position)
        elif (row + 4) % 6 == 0:
            for column in range(self.columns):
                if (column + 5) % 6 == 0:
                    self.put_bomb(row, column)
                if (column + 4) % 6 == 0:
                    self.put_bomb(row, column)
                if (column + 1) % 6 == 0:
                    self.put_bomb(row, column)
        elif (row + 3) % 6 == 0:
            for column in range(self.columns):
                if (column + 2) % 6 == 0:
                    self.put_bomb(row, column)
                if (column + 1) % 6 == 0:
                    self.put_bomb(row, column)
        elif (row + 2) % 6 == 0:
            for column in range(self.columns):
                if (column + 6) % 6 == 0:
                    self.put_bomb(row, column)
                if (column + 5) % 6 == 0:
                    self.put_bomb(row, column)
                if (column + 2) % 6 == 0:
                    self.put_bomb(row, column)
        elif (row + 1) % 6 == 0:
            for column in range(self.columns):
                if (column + 3) % 6 == 0:
                    self.put_bomb(row, column)
        else:
            print("Something went very wrong in the bomb placements")

The hardest part about writing the code for the patterns related to going all the way to the edge but at the same time avoiding to grab a coordinate that doesn’t exist.

Then the player is given start coordinates, the board including the player is drawn (written :-)) graphically, and the player is given the possible directions to take. The game now starts, and for each move, the eventuality of the player being home free is checked, the existence of a bomb at the new place is checked, the board including the path of the player is drawn in its new state, and new possible directions are given.

I don’t know how many people will get to this point in my explanation, so thank you so very, very much for giving meaning to my work :-)

Click the buttons below to watch the python files in their complete form:

Click this button to download all of the files and PLAY THE GAME:

Task

Make objects that represent a deck of cards and two players, and make them play the card game “War” against each other.

Solution

As the other projects presented on this site, also this one was made with the purpose of learning how to code. However, this project is a very early work and must be assessed with that in mind.

The solution consists of four .java-files, each containing a class that takes on a particular role:

  • “class Player”: A player object has a name and holds cards. Through different functions, a player can have cards looked upon, taken away and given.
  • “class Card”: A card object has a suit and a value. A card comprises a function that returns its value.
  • “class CollectionOfCards”: An object made from this class is an ArrayList holding card objects. Through different functions, such a collection of cards can be mixed randomly, its first card can be fetched and then looked upon through the card’s own function, and it can have cards being removed from it and given to it.
  • “class CardGames”: This class is not used to create objects, instead this is simply the place where the player objects, card objects, collection objects and the game itself is created, set into motion and eventually finishes.

Below you see the entire code in ‘CardGames.java’.

Beforehand let me just tell you the rules of the game “War”: First, all of the 52 cards are handed out to the two players, each holding their cards in a pile. Then the game starts by the players showing each other their top card, and the player with the highest value takes both cards and puts them in the bottom of his/her stack of cards. If the values are equal, each player put three more cards into the pool, and the player’s fifth cards are compared to settle who take all the cards in the pool. If other equalities in value should occur, the previous procedure is repeated. In the end, one of the players holds all cards and thereby won the game.

Now for the code of ‘CardGames.java’:

import java.util.ArrayList;

public class CardGames {

    public static void main(String[] args) {
        
        //To spillere oprettes
        Player john = new Player("John");
        Player bruce = new Player("Bruce");

        //Kort oprettes og lægges i bunkens kortholder-array
        ArrayList<Card> bunkensKortholder = new ArrayList<Card>();
        for (int værdiTal = 2; værdiTal <= 14; værdiTal++) {
            Card nytKorth = new Card('h',værdiTal);
            bunkensKortholder.add(nytKorth);
            Card nytKortr = new Card('r',værdiTal);
            bunkensKortholder.add(nytKortr);
            Card nytKortk = new Card('k',værdiTal);
            bunkensKortholder.add(nytKortk);
            Card nytKorts = new Card('s',værdiTal);
            bunkensKortholder.add(nytKorts);
        }
        
        //Kortholder-array'et lægges ind i bunke-objektet
        CollectionOfCards bunken = new CollectionOfCards(bunkensKortholder);
        
        //Kortene blandes og fordeles til de to spillere
        bunken.blandKort();
        System.out.println("Kort fordeles til de to spillere.");
        int kortOprindeligtIBunken = bunken.antalKort();
        for (int x = 0; x < kortOprindeligtIBunken / 2; x++) {
            john.fåKort(bunken.seØversteKort());
            bunken.udØversteKort();
            bruce.fåKort(bunken.seØversteKort());
            bunken.udØversteKort();
        }
        
        //Spillet går i gang
        System.out.println("Spillet går i gang.");
        int rundetæller = 1;
        while (john.antalSpillerKort() != 0 && bruce.antalSpillerKort() != 0) {
            System.out.println("Runde " + rundetæller++);
            int A = john.seSpillerKort(0).fåVærdi();
            int B = bruce.seSpillerKort(0).fåVærdi();
            if (A > B) {
                john.fåKort(bruce.seSpillerKort(0));
                bruce.givKort(bruce.seSpillerKort(0));
                while (bunken.antalKort() > 0) {
                    john.fåKort(bunken.seØversteKort());
                    bunken.udKort(bunken.seØversteKort());
                }
            }
            else if (A < B) {
                bruce.fåKort(john.seSpillerKort(0));
                john.givKort(john.seSpillerKort(0));
                while (bunken.antalKort() > 0) {
                    bruce.fåKort(bunken.seØversteKort());
                    bunken.udKort(bunken.seØversteKort());
                }
            }
            else {
                if (bruce.antalSpillerKort() > 4 && john.antalSpillerKort() > 4) {
                    for (int x = 0; x < 4; x++) {
                        bunken.indKort(bruce.seSpillerKort(0));
                        bruce.givKort(bruce.seSpillerKort(0));
                        bunken.indKort(john.seSpillerKort(0));
                        john.givKort(john.seSpillerKort(0));
                    }
                }
                else if (bruce.antalSpillerKort() > john.antalSpillerKort()) {
                    while (john.antalSpillerKort() > 0) {
                        bruce.fåKort(john.seSpillerKort(0));
                        john.givKort(john.seSpillerKort(0));
                    }
                }
                else {
                    while (bruce.antalSpillerKort() > 0) {
                        john.fåKort(bruce.seSpillerKort(0));
                        bruce.givKort(bruce.seSpillerKort(0));
                    }
                }
                rundetæller--;
            }
        }
        
        //Vinderen findes og spillet afsluttes
        String vinder;
        if (john.antalSpillerKort() != 0) vinder = john.fåNavn();
        else if (bruce.antalSpillerKort() != 0) vinder = bruce.fåNavn();
        else vinder = "IKKE FUNDET!!! AAAAHHHHH!!!";
        System.out.println("Vinderen er " + vinder);
    }

}

Obviously, John is a better player than Bruce:

The rounds and their numbers are listed, and in the end John is declared as the winner

He does it!

The rounds and their numbers are listed, and in the end John is declared as the winner

He does it again!

The rounds and their numbers are listed, and in the end Bruce is declared as the winner

Of course also an idiot can win in this game...

Click the buttons below to watch the java files in their complete form:

Click this button to download all of the files and PLAY THE GAME:

Task

Build and program a LEGO machine that can sort bricks based on their color.

Solution

The build: A LEGO machine consisting of two conveier belts with individual motors, the outer conveier belt turnable through a third motor, and consisting of an object sensor and a color sensor.

The program: A program made in the LEGO MINDSTORM GUI that first of all makes the conveier belts move. This is temporarily stopped, when the object sensor detects a degree of object covering that suggests, that more than one brick is there. At that point, the conveier belts move taking turns in very short intervals, the outer one moving more each time which eventually increases the distance between the sensed bricks. After that, the conveier belts again move as in the beginning, which is also temporarily stopped, whenever the color sensor senses a color between yellow, red, blue or a color different from those three. At that point, the third motor is instructed to position the outer conveier belt over one of four sorting boxes, and then the outer conveier belt’s motor makes the brick go into the appropriate box.

Below you'll find:

  • a video of the machine and program in action
  • fotos of the machine
  • a graphical representation of the program
Video
Fotos
The machine from a certain angle: Outer conveier belt motor in the bottom right, color sensor in the top, and sorting boxes on the left

Outer conveier belt motor in the bottom right, color sensor in the top, and sorting boxes on the left

The machine's brick-input spot

In the back: Brick-input

Different constructions prevents the brick from laying on one of its four sides before getting onto the inner conveier belt

The brick is prevented from laying on one of its four sides before getting onto the inner conveyor belt

The outer conveier belt with color sensor

Outer conveyor belt with color sensor

The machine from above

From above

The machine from the side: The motor in the bottom turns the outer conveier belt

From the side: The motor in the bottom turns the outer conveyor belt

The machine from above: The sensor that controls traffic and the programmable brick

Top-down: The sensor that controls traffic and the programmable brick

Graphical representation of the program
The program as constructed in the LEGO MINDSTORMS GUI

The program as constructed in the LEGO MINDSTORMS GUI